Opened 5 months ago
Last modified 5 months ago
#58769 new defect (bug)
HTTP/3 Early-Data/0-RTT replay attack
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | major | Version: | 6.3 |
Component: | Security | Keywords: | |
Focuses: | Cc: |
Description
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)
EDIT: just found out 0-RTT is enabled by default on Cloudflare, so this is something (especially the nonced GET requests) that need to be addresses rather sooner than later.