[wp-trac] [WordPress Trac] #60205: Automatically protect misconfigured sites from BREACH attacks
WordPress Trac
noreply at wordpress.org
Sun Jan 7 12:03:41 UTC 2024
#60205: Automatically protect misconfigured sites from BREACH attacks
-------------------------+-----------------------------
Reporter: kkmuffme | Owner: (none)
Type: enhancement | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Security | Version: trunk
Severity: normal | Keywords:
Focuses: |
-------------------------+-----------------------------
Foreword:
I'm by no means an expert in security issues, I'm reporting this, since I
encountered this vulnerability on a service/CDN that was supposed to have
this patched, but didn't properly, indicating the difficulty to prevent
this vulnerability downstream.
All feedback and discussion welcome.
---
This is **not a security issue in WP itself**, but rather an issue of
and/or:
- page cache plugins
- misconfigured servers
- misconfigured CDNs
and helped by the fact that WP's CSRF/nonce system is not unique per
request.
In some cases/plugins, the vulnerability is made worse by only checking
the nonce without checking user permission (current_user_can)
---
The vulnerability:
Lots of servers use apache/nginx's gzip (and/or brotli), as well as some
CDNs and page cache plugins offer automatic compression.
Unfortunately, this allows for BREACH attacks with nonce when $_GET or
$_POST data are output in the page (even when escaped/sanitized for
output, since nonce are alphanumeric only)
Theoretically, this also applies when $_COOKIE data is output in the page
directly, however
---
The solution: (if I understood it correctly)
HTP https://ieeexplore.ieee.org/document/9754554
Basically, whenever the page has `! empty( $_GET ) || ! empty( $_POST )`
we output a random number with length n - to further secure this, n is a
number between x and y.
Practically a string with length 10 is sufficient for most cases as shown
in the research paper.
Practically, I guess using a `<meta name="<?php echo random_int( 20, 30 );
?>">` in the <head> is sufficient.
Ideally we would hook it to multiple places (header, body, footer) and
internally call remove_action once it's been output once.
This prevents issues for where the header/body/whatever isn't executed
(e.g. bc it's cached as a fragment)
Addiitonally, it should be filterable (to disable) in case a page cache
already implements this feature or in cases where people know they have
correctly configured their server(s), to prevent duplicate HTB
unnecessarily increasing the response size*
*since the only case this solution will not prevent BREACH is when using
HTTP 1.1 with "chunked" where each chunk is gzipped too. This can only be
mitigated by a page cache or apache/nginx/CDN itself, bc adding the
randomness to all chunks or disabling compression when serving chunked.
---
Why in WP?
- fixing this otherwise requires lots of servers to be reconfigured
correctly
- CDNs get it wrong too
- it's a super simple fix
- the increase in total request size is minimal (<= n bytes in the best
case, n+markup in the worst case, which is still probably <0.1% of an
average WP response)
Why in all cases and not only when e.g. nonce is called?
The effort to comb through the whole codebase and identify
functions/places that can cause this, is not worth the effort, given the
disadvantages are minimal.
Why not only if Accept-Encoding header is present?
Since the request might be from a CDN that does not support encoding for
origin requests, will transform the request for the client, introducing
the vulnerability.
Why not in a HTML comment (<!-- HTB-here -->)?
HTML comments are removed from output depending on PHP opcache
configuration.
--
Ticket URL: <https://core.trac.wordpress.org/ticket/60205>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list