[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