How To Understand and Stop This DOS Attack From Boring Your Server to Death

Java developer Vlad Ionescu created a guide for understanding the Slowloris DoS attack and shares a plan for how to protect against it

The consequences of a malicious web attack can run deep, causing users to reach new depths of annoyance and irritation. As attacks become smarter and more abundant, it’s important to understand the various attacks that a user is susceptible to and how to protect themselves in the unfortunate chance they find themselves victim to one. 

What is Slowloris attack? 

According to Wikipedia, Slowloris is a type of denial of service attack tool which allows a single machine to take down another machine’s web server with minimal bandwidth and side effects on unrelated services and ports.

How does a Slowloris attack work? 

A client sends a request to a web server asking for a page, but it never completes the request. The server hangs there, waiting for the request to be completed or until a connection timeout occurs. Then, just before the connection times out, it sends an extra piece of tiny data in order to fool the server that the request is not over yet. Therefore the request will not be finished and the server won’t timeout the connection. 

The server cannot recognize this behaviour as an attack because it might be due to a poor internet connection on the client’s end. This process of re-sending the tiny piece of data is done in a loop, at a specific time, hence occupying that connection forever. 

Repeat this process by opening as many connections as the server has. This will exhaust the thread connections pool of the server, leaving no room for other (real) incoming requests –  actually accessing the web page in the browser, for example. 

Analogy 

You can picture this as a conversation someone has with other people at the same time. He can have as many conversations as he can pay attention to and not be driven mad. Once that number is reached and a new guy comes in asking for something, then the 1st person can’t pay attention to him because his brain is already full. 

Which web servers are affected? 

The most affected web servers are Apache Tomcat based ones. See below for the officially documented security vulnerability.

How it works, from a technical point of view 

The above is an example of a HTTP request sent over the wire and how the anatomy of it. Each time we send a GET request to the server, it gets translated like this: 

GET / HTTP/{http_version} CRLF 

{header_1}: {header_1_value} CRLF 

{header_2}: {header_2_value} CRLF 

{header_n}: {header_n_value} CRLF 

CRLF 

Each time we write something on one line, the line ends with CRLF – which stands for Carriage Return Line Feed. This allows the server to recognize the headers enumeration. We know the request to the server is finished when it ENDS just with CRLF.

Web application setup 

Above is a sample “hello” web application delivered by Apache. The application is deployed on apache-tomcat-7.0.28 (the last version affected by this vulnerability) and is run on the localhost. In Tomcat versions prior to this one (and this one included), the default HTTP connector is blocking and follows a one thread per connection model. This means that in order to serve 100 concurrent users, it requires 100 active threads. 

Server setup 

In the above screenshot is described the server.xml config file for Apache Tomcat server. It defines a connectionTimeout of 5000 milliseconds. This states the following: release this connection after 5 seconds if it’s not used. By default, Tomcat uses a maximum number of 200 threads.

Attack code 

The above screenshot depicts the Main class that will fire 200 different threads, each one representing a new connection. On line 11, the code waits “a bit” before creating each connection because otherwise these will happen very fast and will not become connections yet, but rather stacked in an acceptedCount queue. If this server config parameter has a value of, for example, 10, the creation of sockets will break – since we will create 200 items very fast and some of them will be stacked (200 > 10). 

In the above we define some constants for the following: where the application is deployed (localhost), on which port (8080) and what is the application path (/sample). In addition, we also

establish what will be the interval in which we will be sending the tiny piece of information over and over again (every 2 seconds). 

In the run() method, we defined the thread code that will attack the server.

Above is where the “magic” happens. At line 29, we are creating a new connection using sockets. In lines 32-34 we’re using the HTTP method GET for getting the root application page and NOT ending the request (no “extra” \r\n present at the end). The /r/n represents the CRLF.. In lines 37-41 we’re waiting 2 seconds and then we send a custom header. We will repeat this process forever, hence creating the Slowloris DoS attack. We could have “waited” between 1 and 4 seconds because we defined the connectionTimeout = 5 seconds (if we wait >= 5 seconds, the connection will timeout and we no longer can write to the socket). In lines 43-46 we check that if something goes wrong then we will repeat the whole process (recreate the connection, send header, etc).

Demo – attack the vulnerable server (successful) 

Let’s start the Apache Tomcat server version (7.0.28) vulnerable to this attack. 

Let’s open up the application.

Now, let’s run the attack code.

We can see that all 200 threads have started. Now if we go to the application and refresh it or just try to click on a link it will wait (i.e. servlet link). See the loading circle from the tab and the “Waiting for localhost…” message at the bottom of the picture. 

The attack is working. The page won’t reload unless the attacking code stops or the request made “catches a break” and “slips” to the server so it will be resolved and the requested page will be returned. However, this is not something we can decide/compute or foresee when it’s going to happen or if it’s going to happen. If it does and the page requested is returned, next time when we access the application, we will wait again.

Now let’s stop the application. 

See above the message “Process finished with…” This means that the application was stopped.

Let’s check the page again now. 

We can see now that the application is working because it displayed the previous link we’ve clicked (the servlet link). 

Demo – attack the non-vulnerable server (unsuccessful) 

Let’s start the Apache Tomcat server version (9.0.41) which is not vulnerable to this attack.

Let’s open the same application but deployed on this server version.

Again, let’s start the code. 

We can see that the 200 threads have started. Now, let’s check the application and try to click on the jsp link.

We can see that the application has loaded now without the need to stop the attack code. This is due to the fact that the code doesn’t have any effect on the non-vulnerable server. The 9.0.41 version uses the NIO connector for handling HTTP requests which is a non-blocking one. 

Mitigations 

  • Upgrade to a version of Tomcat which is not vulnerable to this kind of attack. This version will use (by default) Non-blocking NIO connector instead of the default blocking BIO one (org.apache.coyote.http11.Http11NioProtocol instead of HTTP/1.1). 

Example of configuring this in server.xml config file: 

<Connector connectionTimeout=”20000″ maxThreads=”1000″ port=”8080″ protocol=”org.apache.coyote.http11.Http11NioProtocol” redirectPort=”8443″/> 

  • Use a non-thread based server as a proxy. 
  • Limit the number of connections an IP can have. 
Background Image