You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I reported this privately in 2023, and was told "we do not feel it need to be fixed, as it is valid HTTP request, it is the backend responsibility to properly handle it."
I now report it publicly :)
Overview
When OLS is acting as a gateway, and it receives an HTTP request that uses a \n alone (i.e., not \r\n) to separate headers, it forwards the \n without normalizing it to \r\n. This is prohibited by the RFCs, and is usable to execute request smuggling attacks when OLS is acting as a gateway for certain origin servers.
OLS's behavior
OLS, when acting as a gateway, will transform request $A$ into request $B$:
A sender MUST NOT generate protocol elements that do not match the grammar defined by the corresponding ABNF rules.
Thus, it is a violation of the standard for OLS to forward a header delimited by \n alone when acting as a gateway.
It's worth noting that RFC 9112 allows a recipient to choose to accept messages with \n instead of \r\n. This does not extend to senders.
How this can be exploited
Some origin servers allow \n within header values. Thus, if you send a Content-Length header that is separated from the previous header with only \n, that Content-Length header will be visible to OLS but not processed by the origin server.
For a concrete example, consider the following payload:
POST / HTTP/1.1\r\n
Host: whatever\r\n
Test: a\n
Content-Length: 38\r\n
\r\n
GET /evil HTTP/1.1\r\nHost: whatever\r\n\r\n
If you send this payload through an OLS gateway, it sees one request, with a 38-byte message body.
When the gateway forwards this, the origin server sees two requests, because the value of the Test header is interpreted as a\nContent-Length: 38, so no Content-Length header is found. This second request was never validated by the gateway (i.e., it was smuggled).
This can be reproduced using the HTTP Garden with the following sequence of commands:
Notice that though Daphne is one of the affected origin servers, it's still in compliance with the RFCs, because the RFCs permit recipients to replace bare LF with SP before processing. This is what Daphne does.
It's not reasonable to expect the backend to handle bare LFs the same way that OLS does because the RFCs allow more than one valid interpretation of bare LF-separated headers. Bare LF is inherently ambiguous, which is why a gateway MUST normalize LF to CRLF.
I reported this privately in 2023, and was told "we do not feel it need to be fixed, as it is valid HTTP request, it is the backend responsibility to properly handle it."
I now report it publicly :)
Overview
When OLS is acting as a gateway, and it receives an HTTP request that uses a
\n
alone (i.e., not\r\n
) to separate headers, it forwards the\n
without normalizing it to\r\n
. This is prohibited by the RFCs, and is usable to execute request smuggling attacks when OLS is acting as a gateway for certain origin servers.OLS's behavior
OLS, when acting as a gateway, will transform request$A$ into request $B$ :
Request$A$ (the incoming request to OLS)
Request$B$ (the outgoing request from OLS)
Notice the bare
\n
after the request line andTest
header.How this violates the RFCs
The RFC 9112 grammar requires CRLF line endings:
RFC 9110 Section 2.2 says this:
Thus, it is a violation of the standard for OLS to forward a header delimited by
\n
alone when acting as a gateway.It's worth noting that RFC 9112 allows a recipient to choose to accept messages with
\n
instead of\r\n
. This does not extend to senders.How this can be exploited
Some origin servers allow
\n
within header values. Thus, if you send a Content-Length header that is separated from the previous header with only\n
, thatContent-Length
header will be visible to OLS but not processed by the origin server.For a concrete example, consider the following payload:
If you send this payload through an OLS gateway, it sees one request, with a 38-byte message body.
When the gateway forwards this, the origin server sees two requests, because the value of the
Test
header is interpreted asa\nContent-Length: 38
, so noContent-Length
header is found. This second request was never validated by the gateway (i.e., it was smuggled).This can be reproduced using the HTTP Garden with the following sequence of commands:
It's clear from the output that these four origin servers all see two requests where OLS sees only one.
Suggested fix
OLS should implement one of the following in order to comply with the RFCs and fix the issue:
\n
into\r\n
before forwarding headers.\n
line endings.The text was updated successfully, but these errors were encountered: