Inspired by an article by Watchfire from 2005, we recently explored an old attack technique named HTTP Request Smuggling and checked it against our WAF protection. By coincidence, it turned out someone else was also exploring this technique at the same time.
Given the hype it received as a result, we’re going to look at some HTTP Desync attacks we’ve seen in the wild and explain how we can defend against them.
HTTP Desync attacks abuse the way a chain of HTTP servers (i.e. front-end and back-end web application server deployments) interpret consecutive requests – especially the way HTTP servers determine the boundaries or length of each request.
As HTTP specifications (RFC) allow the boundaries/length of requests to be parsed in several ways, discrepancies can arise between the servers handling consecutive requests, allowing an attacker to potentially bypass security measures, interfere with other user sessions, and gain unauthorized access to sensitive data.
For more information on the nature of these kind of attacks, check the following article.
HTTP Desync Attacks
Let’s look at some attacks seen in the wild.
We added a few rules to our WAF to catch the HTTP anomalies described in the articles above.
The first HTTP anomaly we’ve seen being used is a request that consists of a Transfer-Encoding header with a value that isn’t specified in the RFC 7230, section 4: Transfer Codings specification. This is done in an attempt to hide the encoding of the payload from the WAF in the hope that the origin won’t be as strict on the exact header value and will therefore process the request.
Another HTTP anomaly we’ve seen is a Content-Length header with a Transfer-Encoding header with a value of chunked.
There are two possible scenarios here:
- Content-Length value is smaller than the chunked payload size.
The origin server will check the Content-Length header to determine the length of the request, but there will be some leftover payload that will be concatenated to the next incoming request.
- Content-Length value is larger than the chunked payload size.
The origin server reads the Content-Length header as in the previous case, but this time the connection won’t be closed after the current request as it will wait for more incoming bytes, resulting in a timeout on the next server in the chain waiting for the next request to arrive.
In both scenarios, an attacker might construct a two-step payload so that, by concatenating the second request to the first, a malicious payload will be received. However, the WAF will never see the full malicious request so its rules won’t apply.
Indeed, we only saw several thousands of requests of this type, used by what seemed to be a fuzzer. As a consequence, many of the requests didn’t make much sense.
One of the few payloads that did make sense looked like this:
In the payload above we can see a chunk with a size of 16 (10 in hexadecimal), followed by the chunk payload, and then the end of chunks marked by a chunk size 0.
According to a Transfer-Encoding: chunked header value format, this should be all the payload but, as you can see, there’s more following it – X.
That’s the payload that’s being attempted to be smuggled through the WAF.
The next example of attacks we’ve seen shows the use of duplicate Content-Length headers with different values over the course of more than two weeks, during which time there was a total of about 80,000 requests, all made by Nikto vulnerability scanners.
The idea behind using duplicate headers is that the WAF would see one and the origin server would see the other, causing them to see different payloads. That way, there’s room to smuggle a malicious payload that will affect the origin server.
For example, when sending two Content-Length headers:
If the WAF reads the Content-Length value from the first header it won’t see the full payload while, if the origin server reads the same value from the second Content-Length header, it will see the full request with requested param value of password file in /etc directory potentially returning the file content.
We’ll finish this section with an example of an attack using several HTTP Desync bypass techniques – a preceding space in front of the header name, and a Transfer-Encoding header with chunk size 0 and a Content-Length header.
This attack sends a specially-crafted payload in the hope of bypassing an XSS payload through the WAF. The origin server might interpret the url with the <img ..alert(1)> as part of its query string as a second request, while the WAF might think it’s payload of the first request.
HTTP Desync Defense Methods
Now let’s talk about how we can defend against this type of technique.
The issue with mitigating HTTP Desync Attacks is that legitimate requests sometimes use the same techniques as those used in these kind of attacks, which means a simple block won’t be suitable.
Since the basis for this technique is the discrepancy in how two HTTP devices see a request, all requests of this type will use some kind of an RFC payload that different HTTP parsers will interpret in a different way.
What we need to do is make sure the WAF sees that the request is in the RFC-borderline area or sees the payload that’s intended to pass to the origin, in order to be able to provide mitigation.
For that we added the following capabilities for Cloud WAF and On-Prem WAF:
- Block duplicate headers using two separate values
- Block non-RFC values, e.g Transfer-Encoding: xchunked (instead of the valid value chunked)
- Normalize spaces around header names
- Block requests with \r or \n in header names
- Block requests with both Transfer-Encoding and Content-Length, where the length doesn’t match the payload size
Defending against this technique requires us to consider edge cases in HTTP RFC standard, and to be more strict in the HTTP parsing when considering the security aspect of the requests. However, this, as always, can come at the price of blocking legitimate traffic that isn’t coherent with best practice usage of the HTTP standard.
HTTP Desync Attack is an old technique that still presents a threat even today. It’s important, therefore, that we stay vigilant and remain mindful of how we can defend against it.
Try Imperva for Free
Protect your business for 30 days on Imperva.