Not too long ago, a colleague and I came across this almost forgotten attack vector, which swiftly resurfaced when Portswigger added it to their portfolio of web vulnerability checks in their fantastic tool, Burp Suite Pro. This attack is quite interesting and different from the usual web vulnerabilities such as SQL injection and path traversal, which, unfortunately, we still see in the wild. In this blog post I will shed some light on what HTTP Request Smuggling is and why it should, once again, be taken seriously.
The standard webserver of today often does not stand alone when handling requests. Especially in larger environments, where the traffic of a website visitor, might go through a Web Application Firewall (WAF), a load balancer, or other systems, before reaching the target webserver.
A simplified illustration of a typical HTTP request to a website with a load balancer in play would look like this:
This setup is very common and does its job, but an inconvenient state might occur if conditions are just right, and an attacker takes advantage of this.
The HTTP standard has two ways of defining how large a request is. It can be done with “Content-Length” and “Transfer-Encoding” headers. Most of us are familiar with Content-Length, which usually looks like so:
The lesser known way of defining the size of a request, “Transfer-Encoding”, looks like so:
So, what does this have to do with anything? Well, whether it is a load balancer, WAF or webserver, usually only one of the two ways of defining the length, is supported. A couple of scenarios might then occur:
Scenario 1: The load balancer supports “Content-Length” and the webserver supports “Transfer-Encoding”
Scenario 2: The load balancer supports “Transfer-Encoding” and the webserver supports “Content-Length”
What might happen if we send a HTTP request, where both types are defined simultaneously and scenario 1 is in effect?
Let’s have a look:
In this case, the request is received at the load balancer first, which only looks at the Content-Length. It is specified to be 18, which is:
0 (1 byte) and line break (2 bytes)
A line break (2 bytes)
Parameter=xyz (13 bytes)
To the load balancer, this is a valid definition and a valid request. The load balancer, therefore, forwards it to the webserver.
The webserver, which only supports Transfer-Encoding, sees the 0 and interprets this as: “this is the last chunk, we are done”. So, what happens to “parameter=xyz”? This is where it gets interesting. It becomes the first part of the next request received by the webserver as if it were sent by someone else! In this case, “parameter=xyz”, won’t make any sense since a valid HTTP request begins with “GET /abc…” or “POST /abc…”.
So, let’s try that shall we?
In the example above, the request for “/other-page” would be “smuggled” and seen as the next request going to the webserver and effectively means that the next person, who requests a page, any page for that matter, served by the same webserver, would perform and get the response to our smuggled request!
So, what can an attacker do with this? Depending on the type of software on the load balancer and webservers in play, and how they are configured, an attacker might be able to:
Redirect a user to a completely different, malicious site, to steal cookies or perform a phishing attack
Redirect a user to a page on the same, vulnerable webserver, which performs some malicious action, for example, “GET /administration/create-user.php?username=hacker&password=SecretPassword123”
Performing a denial of service attack by spamming the webserver with requests for a large resource, forcing the webserver to send this large file multiple times
And many more
As I mentioned earlier, HTTP Request Smuggling is only possible if certain conditions are met. The most important one is how the connections between the front-end and back-end systems are established and used. It is only possible to perform the attack if the following is true:
Reuse of back-end connections – this enables the front-end server to send multiple HTTP requests over the same connection
HTTP/2 is not used - HTTP/2 itself does boundary checks for requests and makes sure that the front-end and back-end are in agreement
The examples in this post are not the only ways of performing HTTP Request Smuggling. Other methods include obfuscating the “Content-Length” or “Transfer-Encoding” headers in such a way that they are either ignored or misunderstood by the frontend or backend systems, leading to the same scenarios as in the examples above.
It is important to note that the impact of a HTTP Request Smuggling vulnerability can vary greatly. It depends on both the frontend and backend systems in play and the actual web applications served by the vulnerable infrastructure. That being said, it should definitely be taken seriously.