Slow HTTP attacks rely on the fact that the HTTP protocol, by design, requires requests to be completely received by the server before they are processed. If an http request is not complete, or if the transfer rate is very low, the server keeps its resources busy waiting for the rest of the data. If the server keeps too many resources busy, this creates a denial of service.
These types of attack are easy to execute because a single machine is able to establish thousands of connections to a server and generate thousands of unfinished HTTP requests in a very short period of time using minimal bandwidth.
Due to implementation differences among various HTTP servers, two main attack vectors exist:
- Slowloris: Slowing down HTTP headers, making the server wait for the final CRLF, which indicates the end of the headers section;
- Slow POST: Slowing down the HTTP message body, making the server wait until all content arrives according to the Content-Length header; or until the final CRLF arrives, if HTTP 1.1 is being used and no Content-Length was declared.
The scary part is that these attacks can just look like requests that are taking a long time, so it’s hard to detect and prevent them by using traditional anti-DoS tools. Recent rumors indicate these attacks are happening right now: CIA.gov attacked using slowloris.
QualysGuard Web Application Scanner (WAS) uses a number of approaches to detect vulnerability to these attacks.
The request sent to the first connection consists of a request line and one single header line but without the final CRLF, similar to the following:
GET / HTTP/1.1 CRLF
Connection: keep-alive CRLF
The request sent to the second connection looks identical to the first one, but WAS sends a follow-up header line some interval later to make the HTTP server think the peer is still alive:
Referer: http://www.qualys.com/products/qg_suite/was/ CRLF
Currently that interval is approximately 10 seconds plus the average response time during the crawl phase.
WAS considers the server platform vulnerable to a slowloris attack if the server closes the second connection more than 10 seconds later than the first one. In that case, the server prolonged its internal timeout value because it perceived the connection to be slow. Using a similar approach, an attacker could occupy a resource (thread or socket) on that server for virtually forever by sending a byte per T – 1 (or any random value less than T), where T is the timeout after which the server would drop the connection.
WAS does not report the server to be vulnerable if it keeps both connections open for the same long period of time (more than 2 minutes, for example), as that would be a false positive if the target server were IIS (which has protection against slow header attacks, but is less tolerant of real slow connections).
Slow POST Detection
To detect a slow POST (a.k.a. Are-You-Dead-Yet) attack vulnerability (QID 150085), WAS opens two other connections, and uses an action URL of a form it discovered during the crawl phase that doesn’t require authentication.
The request sent to the first connection looks like the following:
POST /url_that_accepts_post HTTP/1.1 CRLF
Host: host_to_test:port_if_not_default CRLF
User-Agent: Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0;) CRLF
Connection: close CRLF
Referer: http://www.qualys.com/products/qg_suite/was/ CRLF
Content-Type: application/x-www-form-urlencoded CRLF
Content-Length: 512 CRLF
Accept: text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 CRLF
Similar to the slow headers approach, WAS sends an identical request to the second connection, and then 10 seconds later sends the following (again without the final CRLF):
WAS considers the target vulnerable if any of the following conditions are met:
- The server keeps the second connection open 10 seconds longer than the first one, or
- The server keeps both connections open for more than 120 seconds, or
- The server doesn’t close both connections within a 5 minute period (as WAS limits slow tests to 5 minutes only).
WAS assumes that if it is possible to either keep the connection open with an unfinished request for longer than 120 seconds or, even better, prolong the unfinished connection by sending a byte per T – 1 (or any random value less than T), then it’s possible to acquire all server sockets or threads within that interval.
WAS also performs a supplemental test to determine unhealthy behavior in handling POST requests, by sending a simple POST request to the base URI with a relatively large message body (65543 Kbytes). The content of the body is a random set of ASCII characters, and the content type is set to application/x-www-form-urlencoded. WAS assumes that if the server blindly accepts that request, e.g. responds with 200, then it gives an attacker more opportunity to prolong the slow connection by sending one byte per T – 1. Multiplying 65543 by the T – 1 would give you the length of time an attacker could keep that connection open. QID 150086 is reported on detection of that behavior.
Tests performed by WAS are passive and as non-intrusive as possible, which minimizes the risk of taking down the server. But because of the possibility of false positives, care should be taken, especially if the HTTP server or IPS (Intrusion Prevention System) is configured to change data processing behavior if a certain number of suspicious requests are detected. If you are interested in active testing, which might take your server down, you can try some active testing using one of these available tools:
* OWASP HTTP Post Tool (tests against slow headers as well)
Mitigation of slow HTTP attacks is platform specific, so it’d be nice for the community to share mitigation techniques in the comments below. I’ll post an update with information on some of those platforms, as well as general recommendations that can be extrapolated to particular platforms.
Update: Learn about New Open-Source Tool for Slow HTTP DoS Attack Vulnerabilities and download the slowhttptest tool.