Long considered a theoretical attack, HTTP request smuggling is now ‘soaring in popularity’ according to a new research paper published this month. What is HTTP request smuggling and what risk does it pose to your network?
HTTP Request Smuggling (HRS) was first documented back in 2005. It is made possible by the way different web servers implement the HTTP standard – as the standard itself leaves some matters open to interpretation. HRS is also referred to as an HTTP Desync Attack.
Most web server deployments have two of more devices in a chain of systems all talking over HTTP. For example, a load balancer in front of a proxy server, in front of a web application server.
Since HTTP/1.1 it has been possible to send multiple requests in a single long lived TCP/TLS socket – and this approach is often adopted as it is much more performant and efficient than setting up and tearing down a new socket for each request. The HTTP requests are sent back to back and the header for each request is parsed by the server in order to work out where one request ends and the next one starts. However, if the front and back-end servers interpret the headers differently and so place the boundary between two successive HTTP requests in a different place, an opportunity for abuse arises. In particular, contents of the data payload of an HTTP request (which is ignored by the first server) can be turned into a valid HTTP request that is actioned by the second server – in effect being smuggled past the first server and ignored by any defensive logic in place there.
This is possible because the HTTP specification includes two different ways to define the length of a request using two different HTTP headers: Content-Length and Transfer-Encoding. Furthermore, RFC2616 which governs the behaviour of these systems states that:
If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
So, an HTTP request with both headers is valid but if you can find a way to cause the first server to ignore the Transfer-Encoding header it will fall back to use the Content-Length but if the second server does not behave in the same way, then you are able to desynchronise the server chain and smuggle requests. One possible way to do this is by introducing a subtle syntax error into the Transfer-Encoding header that causes a failure in the first server (and so the header is ignored) but is processed successfully by the next server in the chain.
For example:
POST / HTTP/1.1 Host: example.com Content-Length: 33 Transfer-Encoding: xchunked 0 GET /img/a.jpg HTTP/1.1 X:X
If the first server in the chain has a strict parser, the ‘xchunked’ value in the Transfer-Encoding header will be ignored as invalid and the server will fall back to the Content-Length header and send the entire message – including the smuggled request in the last lines.
The next server in the chain, which uses a different software stack, parses the headers differently and ignores the ‘x’ and accepted the ‘chunked’ header and uses the Transfer-Encoding to process the request. Since Transfer-Encoding terminates a chunk of data with a ‘0’ the smuggled request is left in the buffer and not sent on at this time.
A subsequent incoming request arrives at the second server and is appended to the unprocessed smuggled request – making a new request which is only seen by the second server such as:
GET /img/a.jpg HTTP/1.1 X:XGET /js/j.js HTTP/1.1 Host: example.com
In this example the GET command to download the file a.jpg was smuggled past the first server in the chain.
This is an example of a CL.TE style attack, that is both headers are present, the front-end server uses the Content-Length header and the back-end server uses the Transfer-Encoding header.
There are two other flavours of HRS attack:
TE.CL: When both headers are present, the front-end server uses the Transfer-Encoding header and the back-end server uses the Content-Length header.
TE.TE: When both headers are present, 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.
In all variations, the key point is that two successive HTTP servers in the transaction chain can be manipulated to interpret the length headers in different ways allowing the data payload of one HTTP request to be processed as a second HTTP request by a server further down the chain.
HRS can be used to perform attacks such as session hijacking, cache poisoning and circumvention of other security controls as well as exploiting design flaws and vulnerabilities in the web application processing the requests.
How to defend against HTTP Request Smuggling
Since HRS relies on a difference in behaviour between the different servers in the chain, it is only possible when those servers are either running different software stacks or different versions of the same software that behave differently when parsing the HTTP request headers.
If you are setting up a new server or have the option to make changes then switching from HTTP/1.1 to HTTP/2 is the easiest defence as it does away with the chunked Transfer-Encoding mechanism in favour of alternatives which are not susceptible to HRS in the same way. This only needs to be done for the links between the servers in the chain, not the public facing side of the first server (although about 97% of web browsers now support HTTP/2)
Another option is to disable the reuse of the socket connections – instead make and break and new connection for each message by adjusting the web server configuration.
Finally, using a Web Application Firewall can defend against HRS both by normalising incoming requests (to remove ambiguity or sloppy syntax designed to confuse downstream webservers) and by inspecting the data payload to look for suspicious content that could be an attempt to smuggle another HTTP request.
You can assess the vulnerability of your web application to HRS and other security threats with a penetration test from SecureTeam.
“We were very impressed with the service, I will say, the vulnerability found was one our previous organisation had not picked up, which does make you wonder if anything else was missed.”
Aim Ltd Chief Technology Officer (CTO)