The following 2 facts allow for request smuggling through LiteSpeed proxies to LiteSpeed[^1], H2O, Libevent, and Mongoose backends.
[^1]: This is cool! Typically, request smuggling vulnerabilities affect heteroegenous setups.
When LiteSpeed is acting as a proxy, and receives a request containing both a Content-Length and a Transfer-Encoding: chunked header, and the Content-Length header comes first, it un-chunks the message body without removing the Content-Length header. The forwarded request thus has two Content-Length headers, which may be conflicting.
Many origin servers, including LiteSpeed itself, prioritize the first Content-Length header over subsequently received ones when processing incoming requests.
To see this for yourself,
Set up OLS as a proxy, pointing at another instance of OLS.
Send the proxy the following request:
POST / HTTP/1.1\r\n
Host: a\r\n
Content-Length: 0\r\n
Transfer-Encoding: chunked\r\n
\r\n
20\r\n
GET / HTTP/1.1\r\nHost: gotcha\r\n\r\n\r\n
0\r\n
\r\n
You should see the proxy forward the following to the backend:
Observe that the origin server logs 2 received requests, and the second one was smuggled through the proxy. You can tell this because it doesn't have X-Forwarded-Host, Accept-Encoding, or X-Forwarded-For headers.
The following 2 facts allow for request smuggling through LiteSpeed proxies to LiteSpeed[^1], H2O, Libevent, and Mongoose backends.
[^1]: This is cool! Typically, request smuggling vulnerabilities affect heteroegenous setups.
Content-Length
and aTransfer-Encoding: chunked
header, and theContent-Length
header comes first, it un-chunks the message body without removing theContent-Length
header. The forwarded request thus has twoContent-Length
headers, which may be conflicting.Content-Length
header over subsequently received ones when processing incoming requests.To see this for yourself,
X-Forwarded-Host
,Accept-Encoding
, orX-Forwarded-For
headers.