[wp-trac] [WordPress Trac] #58769: HTTP/3 Early-Data/0-RTT replay attack

WordPress Trac noreply at wordpress.org
Mon Jul 10 14:18:11 UTC 2023


#58769: HTTP/3 Early-Data/0-RTT replay attack
--------------------------+-----------------------------
 Reporter:  kkmuffme      |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Security      |    Version:  trunk
 Severity:  major         |   Keywords:
  Focuses:                |
--------------------------+-----------------------------
 **This is a security issue non-specific to WordPress**, however WordPress
 has the reach and responsibility to mitigate common user
 misconfigurations.
 (which is why this is reported in Trac and not in HackerOne)

 HTTP/3 support is getting more ubiquitous, but unfortunately a lot of
 people don't know what they are doing; inadvertetly opening up their WP
 for replay attacks when "early data" is used.
 e.g. with Cloudflare, you just need to change a setting to enable 0-RTT;
 Cloudflare will correctly forward the Early-Data header to the origin, but
 the origin (nginx, apache or the application layer like WP) usually miss
 the required handling for that.

 To allow using 0-RTT with WP safely*, I propose:
 1) as early as possible (to avoid performance penalties): if the
 `$_SERVER['REQUEST_METHOD'] !== 'GET'` and `isset(
 $_SEVER['HTTP_EARLY_DATA'] ) && $_SEVER['HTTP_EARLY_DATA'] === '1'`,
 always return status 425 and exit.
 We can do that since the the presence of the header indicates that the
 intermediary knows/supports handling of the 425 status, and will retry the
 request again without early data.
 e.g. Cloudflare already does not allow non-idempotent 0-RTT (e.g. POST)
 requests in the first place, however with nginx 1.25 that supports HTTP/3
 and other CDNs that might not be the case, therefore this makes sense as a
 first, general security barrier.

 2) when validating a nonce and the request method is GET, we need to check
 for the Early-Data header too. Since using a nonce indicates that this is
 not an idempotent request, therefore at risk of replay attacks.
 In that case, we have 2 options:
 a) if `headers_sent()`, return false, since the nonce verification failed
 (since it could have been a replay attack)
 b) else return status 425 and exit


 *safely as in the same safety standard that currently exists with WP nonce
 (which is vulnerable to certain replay attacks already, since it's not
 really a number used only once)

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/58769>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list