TL;DR

HTTP Request Smuggling is not a new issue, a 2005 white paper from Watchfire discusses it in detail and there are other resources too. What I found missing was practical, actionable, how-to references.

This post covers my findings and, hopefully, sheds some light on the intricacies of HTTP Request Smuggling.

Introduction

I was carrying out some research whilst testing a web application that appeared vulnerable to HTTP Request Smuggling. Rather than just identify the vulnerability and prove its existence to the client, I wanted to demonstrate it in action as well.

Attack methods

There are numerous attack methods using HTTP Request Smuggling. For example; Cross-Site Scripting (XSS) where the attacker targets any users of the application rather than the attacker targeting a user directly. Session hijacking (demonstrated in the exploitation section of this post, about halfway down the page). Server-Side Request Forgery (SSRF) is sometimes possible. The list goes on and, and, furthermore, I believe that other attack methods exist which still need to be explored.

There are also different variations of Request Smuggling, which are known by the abbreviations symbolising the headers used in the attack. These are: CL:CL CL:TE TE:TE and TE:CL. The CL stands for the header value Content-Length and the TE value stands for the header Transfer-Encoding. To reduce complexity will only be providing detail about one method of Request Smuggling.

The method of HTTP Request Smuggling I will demonstrate in this write up is known as CL:TE and, with this method, I will be performing Back-End Socket Poisoning.

Finding Request Smuggling

When browsing through a web application using the Burp Suite web proxy you might notice that HTTP Request Smuggling is flagged in the Dashboard tab. This is often overlooked, or treated as a false positive due to a lack of understanding.

It is true that sometimes this vulnerability can be tricky to exploit and demonstrate but with this write up I hope the concept will be clear.

First let’s look at HTTP Request Smuggling being flagged by Burp Suite.

Burp flags this as HTTP Request Smuggling when it sends requests with malformed Content-Length and Transfer-Encoding headers. When one of these responses times out, Burp will flag it as HTTP Request Smuggling.

As can be seen in the below screenshot, the request has no response tab, indicating that the request timed out and HTTP Request Smuggling is present.

Proving it’s there

Once Burp has flagged HTTP Request Smuggling, we need to confirm that it is, in fact, there, and not a false positive.

The process of sending a valid request is shown in the below diagram:

As can be seen above, a valid request is sent. The front-end rewrites the request, adding headers the back-end will expect. The back-end processes this request and returns the expected response.

So, to detect that we have found HTTP Request Smuggling, we must send a malformed request. To do so, in the below example we add a space between the ‘Transfer-Encoding’ header and the colon that follows. The front-end will ignore the ‘Transfer-Encoding: chunked’ and use the ‘Content-Length’ to determine if the request is valid. The front-end then rewrites the header and removes the space making this Transfer-Encoding header valid in the request to the back-end. In this example, the Transfer-Encoding header takes precedence over the Content-Length header when it arrives at the back-end.

The diagram below demonstrates this:

Putting theory into practice!

The below screenshot demonstrates a malicious request. We have our malformed ‘Transfer-Encoding’ header; there is the zero at the start of the request body to terminate the request on the back-end and, also, the ‘X’ used to poison the back-end socket.

If we load this into Intruder and look for a ‘405’ error in the response, this will be an indicator that we have successfully poisoned the back-end socket with our initial request.

As can be seen above, a ‘405 method not allowed’ response is shown. This is because the next request started as ‘XPOST / HTTP/1.1’ and is therefore not a valid request.

This is confirmation we have request smuggling!

PoC and Exploitation

Yes! The fun part!

From what I have read there are a multitude of exploits which can be used with request smuggling, these attacks including:

Reflected XSS to site wide XSS!

Session hijacking and account takeover !

SSRF

Cache Poisoning

Revealing front-end request rewriting

The method of exploitation I will demonstrate in the following examples is of session hijacking and account takeover.

However, with request smuggling all this goes out the window and these cookies are no longer protected !

This method will also reveal the Front-End request rewriting.

To be able to exploit the HTTP request smuggling and hijack a session, a few pre-requisites are needed:

CL:TE Socket Poisoning.

A part of the request should be reflected in the response.

We need to find a request were a part of the request is reflected in the response. In this example I moved the “maincontent_0%24firstname=” parameter and switched it for the last parameter in the request.

The later section of our POST request payload with “maincontent_0%24firstname=” being the last parameter in the request:

Check if the response to this POST request results in the X string being rendered in the response. If the string is rendered, this will be the field in the response body that we will find our exploited user’s request.

The below screenshot confirmed that anything in the last parameter field of our POST request will be rendered in the response body.

Now that:

We have confirmed we can poison the backend socket Have valid POST request parameter input that will be rendered in the response body

We can then smuggle that request and it will be left to poison the back-end socket. The next request to the server will then be appended to our smuggled request and reflected back to us in the same response body as shown above.

Let’s first look at our request that will have our smuggled payload below (in blue text):

As can be seen above, the first request in the pipeline of requests here is a valid post request. The second, in blue is our smuggled payload.

I have highlighted the content length in the smuggled payload as we want to add more content length than that in the request body. This is because we need to give the exploited users request some space in which to place itself in the body of the response.

Exploitation

We load our request with payload into Intruder. While running we will see response content lengths that differ in size. Some will be Intruder returning our own response as we are sending consecutive requests. However, if an unsuspecting user uses the application, we will capture requests they send. These requests they send will be written to the end of our payload and reflected in the response body we receive.

Shown below is the output from Intruder. The differing lengths of the returned responses indicate we have successfully exploited users providing they have been using the application at the same time we have been running the exploit in Intruder.

Upon viewing one of the responses we find in Intruder we can see that a user has had their request appended to our payload. The below screenshot shows a GET request from a user that has the request in its entirety rendered within our response body.

So, providing someone is using the application, there is no need to target a specific user. If the payload is being run in Intruder and someone sends a request to the server, we will capture the request. It will be appended to our smuggled request where we can then steal their session cookie and hijack their account.

Conclusion

So, next time you see this in Burp, take a longer look and consider if you could exploit it. HTTP Request Smuggling can also be a bug bounty cash cow, as they are little understood and little reported.