The cover image is a real life slow loris. While it is a super cute animal
please don't buy it as a pet
Slow loris is a denial of service attack that can wreck havoc in unprotected thread-based web servers such as Apache, created in 2009, by a guy named RSnake (and is one of my favorite DoS attacks 😆)
In order to understand how such an attack works, let's refresh some basics (too bored, show me now)
DoS and DDoS attacks
DoS attack is an attack in which the attacker, seeks to make a machine or network unavailable to its intended users by disrupting the services of the host, either temporarily or indefinitely. The idea behind this attack is that you are trying to crash the machine that is on the business end of this attack, by sending as many requests as possible. Since the machine has a finite amount of resources, if you manage to send more requests than it can handle, the server will go down.
distributed denial-of-service or
DDoS attack, is the next level. Here instead of a single computer, you utilize a bunch of them in order to simultaneously send as many requests as possible to the machine on the other side. Some modern attacks use techniques such as
DNS amplification in order to maximize the impact of the attack.
But the main idea behind a
DoS attack remains the same. As many requests as possible all at the same time. If you manage to send enough the machine will go down. If you don't, it will just laugh in your face.
Such a kind of attack is very difficult to mitigate, especially for smaller organizations with limited infrastructure. Since such attacks use legitimate requests traditional firewall filtering rules do not play well.
Server - Client Communication with HTTP/1.1
Now let's make a quick and dirty recap on how HTTP/1.1 GET requests work.
Say we want to connect to
dev.to. We will send a
GET request to the website, and we say "Hey I want
index.html". The server will send us back
index.html. Then we will send a new
GET request and we will say "Hey I need
logo.png now". And the server will send us the file we requested. This conversation will continue back and forth until we load the page and all of its assets.
A sample HTTP/1.1 GET request header will look like that:
HTTP/1.1 Host: dev.to Accept-Language: en (empty line)
Note that final empty line. This marks the end of the headers, allowing the server to process the request the moment it receives this empty line. This will be very important in a while.
How the slow loris attack works
The idea of a slow loris attack is very simple. Can I send requests so slowly, that I just bore them to death? And the answer is yes, yes you can!
The slow loris is a kind of slow and low attack invented by RSnake in 2009. Instead of sending requests as fast as possible, it sends requests as slow as possible. The attacker splits the HTTP GET request in as many packets as possible, and sends them as slow as possible.
And now Jimmy you might say, "Ok, I know that servers have a timeout built-in for each request. Surely this thing will never work!". Well, this is true. A server has a built-in timeout for each request. Say that we are browsing a site from our phone, and we lose internet connection for some reason. The server will wait a certain amount of time, and then will let the connection go free. This will release the resources for that connection in order to serve someone else.
The problem comes not if we send no data, but we send some data, but painfully slowly. This is how slow loris works. It sends a request to a host, without completing it, and then it waits. And as the server is about to close the connection due to timeout, it sends say the first character of the file it requires. This is like saying "Hey, I am still here, but I have a really bad internet connection!". And then it does this again and again and keeps that connection going as long as it can.
And then does the same process for as many connections as it can open, essentially hogging all the available connections to the server with painfully slow
HTTP GET requests.
This attack is very difficult to detect by a firewall for example because all these are valid HTTP requests, but they are super slow. The user might have a really bad internet connection after all.
Why thread-based web servers are so vulnerable to this attack?
This attack is super effective when used against an Apache Server or any other thread-based web server like Microsoft IIS. The reason why is that the guys and gals working on Apache Server, decided that when a new connection comes, it will be served by a new thread. This is not a bad approach. If the connections come and go as expected, the thread will serve the connection and then will go away. But, if the connections start to linger much longer than it is anticipated, the server's connection limit will be reached. The same goes for other servers too.
Now let's say we have a relatively small website and the server allows up to 200 concurrent connections because beyond that limit, there are so many threads that the whole thing grinds to a halt. The attack will grab all the available connections, and when a new connection gets freed, the attack will grab that too. In the end, it will end up will all the available connections of the server, rendering the site unreachable. The web server will think that there are 200 people browsing the website, where in essence there is a single person browsing the site 200 times really slowly.
Mitigating the Slow Loris attack
There are several techniques to prevent and mitigate the Slow Loris attack. Some involve using a non-thread based server as a proxy. These servers are immune to this kind of attack.
It is possible to configure the web server to allow the client a set amount of time to start sending header data, and to set a minimum transfer rate. The following example configuration does just that
<IfModule mod_reqtimeout.c> RequestReadTimeout header=20-40,MinRate=500 body=20-40,MinRate=500 </IfModule>
It gives the client a maximum of 20 seconds to start sending header data. The client must then send data with a minimum rate of 500 bytes per second and may do it for a maximum of 40 seconds.
It is also possible to configure the server to keep track of the connected IPs and set a limit to the number of connections an IP can have:
<IfModule mod_qos.c> # handle connections from up to 100000 different IPs QS_ClientEntries 100000 # allow only 50 connections per IP QS_SrvMaxConnPerIP 50 # limit the maximum number of active TCP connections to 256 MaxClients 256 # disables keep-alive when 180 (70%) TCP connections are occupied QS_SrvMaxConnClose 180 # minimum request/response speed # (deny clients that keep connections open without requesting anything) QS_SrvMinDataRate 150 1200 </IfModule>
Do you have something to add? Leave a comment below, and thanks for reading!
Top comments (2)
That's a rather unfair statement. When Apache HTTPD was first created, in 1995, epoll() did not exist on sockets.
The MPM event module exists for quite a while now (2012), and it does not have a major issue with slowloris. But just like with the other non-prefork MPMs, not all Apache modules are safe to be used with the event MPM. Most notably mod_php was not thread safe.
Truth is that I was not trying to point fingers at Apache for bad desing or whatever.
The real point is that a design choice made in 1995, became an attack vector 14 years later ☺