Slowloris is an HTTP connection exhaustion attack. The attack involves opening up a large number of HTTP connections from one computer and very slowly sending the request bytes over the connection. In effect, this causes the server to become unresponse and unable to process further requests if certain mitigations are not put in place. Generally slowloris only requires one attacking machine, instead of the multiple machines necessary in botnet DDoS style attacks.
Details about the attack and original implementation can be found here: https://en.wikipedia.org/wiki/Slowloris_(computer_security)
Recently I decided to take a look at the state of nodejs slowloris implementations. Unhappy with the current offerings, I decided to build my own and see what kind of targets I could take down with it.
I decided to use the HTTP POST verb with a large request body at 1MB. 1MB at one byte per 100 seconds is something like 3 years a request - more than long enough.
The attack I wrote opens a raw socket and outputs the HTTP response preamble, the
Content-length headers, and then starts sending random alphanumeric characters at a slow rate. By default, the rate is one byte per 100-110 seconds.
The script also allows the user to input the number of connections for the attack to use. We found that using about 86 connections at 1 byte per 100-110 seconds was enough to take down a default installation of WordPress on a fresh Ubuntu 16.04 server.
I also built the ability to specify how quickly to make the initial connections to the server. If this value is set to a short interval, the operating system may throw a warning about a potential SYN Flood attempt that might raise red flags.
Mitigation / Counter mitigation
In the process of building the attack script, I worked with the operations team closely. Ops spun up a server for me and installed the latest version of WordPress on it. I would then launch my attack until I was happy with the code in the script. Then, Ops would adjust the server configuration in an attempt to mitigate the issue.
Some of the mitigations that Ops tried that didn't work were raising the thread count and changing the mpm backend in apache.
Where Ops had more success was with Apache's
Reqtimeout module. By putting in place this anti-timeout measure, Ops was able to control the timeout for HTTP request headers, and body. By default, the HTTP request header timeout is 40 seconds, meaning if the server doesn't receive all the HTTP headers after 40 seconds the connection is closed.
However, the headers timeout didn't have much effect on the attack, since all the request headers are sent immediately to the server.
Also by default on the
Reqtimeout module are body timeout requirements that 500 bytes per second must be received in order to keep the connection open. I modified my script by adding a flag that would send 500 bytes per second to the server, and was able to circumvent this mitigation measure. However, the total time for a 1MB request was reduced from about 3 years to about 30 minutes - still long enough for pratical purposes.
Request Body Timeout
Where Ops really struck gold was with the request body timeout. Like the headers timeout, it is possible to set a maximum amount of time to wait for the entire HTTP request body to be received. By default,
Reqtimeout sets this value at unlimited, but once a value was supplied I began to run into trouble completing the attack successfully.
For the request body timeout, we found that values above 45 seconds still allowed us to make the site unresponsive by carefully timing how quickly the attack script opened connections to the server. However, for values ranging from 15-30, we were not able to successfully block the server from fulfilling requests.
Modqos can limit the number of connections from a single IP address, which is a successful mitigation against this kind of attack. This may be the most effective mitigation of all.
Also, modsecurity can be configured to blacklist any IP that results in a number of 408 response codes during a certain interval for a certain amount of time.
The script I developed can be found here: https://gist.github.com/nstarke/138179a6ef1158a379561ac6b94d6024
We tested extensively against WordPress on this project, and as such our conclusions apply primarily to WordPress and PHP hosted sites in general.
There are a number of considerations to take into account when deploying a WordPress server. Loading the
Reqtimeout module and changing the default value of the body timeout to something under 30 seconds will go a long way towards mitigating the risk posed by slowloris-style attacks. Loading Modqos and setting the max number of connections from an IP address to something like 50 will also help mitigate the issue.
Suffice to say, if you want to protect your self-hosted WordPress server from slowloris-style attacks, the defaults are not good enough!