HTTP Request Smuggling
For HTTP request smuggling to work the following headers need to be set:
Content-Length: X
Content-Length: X
Content-Type: application/x-www-form-urlencoded
If dual Content-Length: X
is not accepted, instead use chunked encoding by adding the following header (with one content-length):
Transfer-Encoding: chunked
In a chunked message, the body consists of 0 or more chunks. Each chunk consists of the chunk size, followed by a newline (\r\n), followed by the chunk contents
Also, when the Transfer-Encoding == 'chunked', it will stop processing the request at a '0'
If it's the back-end that doesn't support chunked encoding, we'll need to flip the offsets around:
Other Transfer-Encoding: chunked
bypasses include (note the space before):
CT.0:
CL.TE:
For Content Length Transfer Encoding we need the following headers (content length needs to be what is sent before the second chunk):
We can detect potential request smuggling by sending the following request:
Thanks to the short Content-Length, the front end will forward the blue text only, and the back end will time out while waiting for the next chunk size. This will cause an observable time delay.
If both servers are in sync (TE.TE or CL.CL), the request will either be rejected by the front-end or harmlessly processed by both systems. Finally, if the desync occurs the other way around (TE.CL) the front-end will reject the message without ever forwarding it to the back-end, thanks to the invalid chunk size 'Q'. This prevents the back-end socket from being poisoned.
TE.CL:
Specifically to exploit Transfer Encoding Content Length you request the content Length to be less than the data sent.
The content type needs to be less than the command (turn off auto-update in burp repeater). The first request requires the following headers:
Transfer-Encoding: chunked
Content-Type: application/x-www-form-urlencoded
The second (smuggled) request needs to have the following:
Content-Length: X
Content-Type: application/x-www-form-urlencode
We can safely detect TE.CL desync using the following request:
Thanks to the terminating '0' chunk the front-end will only forward the blue text, and the back-end will time out waiting for the X to arrive.
Last updated