Make WordPress Core

Opened 5 months ago

Last modified 5 months ago

#58769 new defect (bug)

HTTP/3 Early-Data/0-RTT replay attack

Reported by: kkmuffme's profile kkmuffme 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)

Change History (1)

#1 @kkmuffme
5 months ago

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.

Note: See TracTickets for help on using tickets.