Skip to content

Instantly share code, notes, and snippets.

@nielsvanderbeke
Created February 14, 2014 08:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save nielsvanderbeke/8997399 to your computer and use it in GitHub Desktop.
Save nielsvanderbeke/8997399 to your computer and use it in GitHub Desktop.
Slow HTTP Attacks

Slow HTTP attacks are denial-of-service (DoS) attacks in which the attacker sends HTTP requests in pieces slowly, one at a time to a Web server. 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. When the server’s concurrent connection pool reaches its maximum, this creates a DoS. Slow HTTP attacks are easy to execute because they require only minimal resources from the attacker.

Attack exploits the fact that most of modern web servers are not limiting the connection duration if there is a data flow going on, and with possiblity to prolong TCP connection virtually forever with zero or minimal data flow by manipulating TCP receive window size value, it is possible to acquire concurent connections pool of the application. Possibility to prolong TCP connection is described in several vulnerability reports: MS09-048, CVE-2008-4609, CVE-2009-1925, CVE-2009-1926 .

Prerequisites for the successful attack are: - victim server should accept connections with advertised window smaller than server socket send buffer, the smaller the better – attacker needs to request a resource that doesn't fit into server's socket send buffer, which is usually between 64K and 128K. To fill up server socket's send buffer for sure, consider using HTTP pipelining (-k argument of slowhttptest)

slowhttptest controls the incoming data rate by manipulating receive buffer size through SO_RCVBUF socket option and by varying reading rate from it by application. Note, that different operating systems might have different behavior. For example, OSX uses the value we set SO_RCVBUF to in initial SYN packet, while Linux systems double this value (to allow space for bookkeeping overhead) when it is set using setsockopt. Minimum doubled value for Linux systems is 256 or the first value of /proc/sys/net/ipv4/tcp_rmem, whichever is larger. Also, changing receive buffer size on OSX doesn't work if connecting to localhost.

For SSL connections, slow reading from receive buffer engages after SSL handshake is finished. However, as initial window size is smaller than usual, handshake might require more TCP packets and last longer than usual.

Readings

Tools

  1. slowloris.pl
  2. slowloris6.pl - IPv6 version
  3. slowhttptest

Mitigate

  1. ModReqtimeout (Recommended) : Source 1, Source 2 , sourcecode
  2. ModQoS (most effective after testing): Source 1
  3. ModSecurity : Source 1 , Source 2 , sourcecode

Test Mitigation

ModReqtimeout

LoadModule reqtimeout_module            /usr/lib64/httpd/modules/mod_reqtimeout.so
# Wait max 10 seconds for the first byte of the request line+headers
# From then, require a minimum data rate of 500 bytes/s, but don't
# wait longer than 20 seconds in total.
RequestReadTimeout header=10-20,minrate=500

# Wait max 10 seconds for the first byte of the request body (if any)
# From then, require a minimum data rate of 500 byte/s.
RequestReadTimeout body=10,minrate=500

Result : stopped the attac after 10 seconds , but allowed to atackker te retry after x time

mod_qos

LoadModule qos_module                   /usr/lib64/httpd/modules/mod_qos.so

<IfModule mod_qos.c>
   # handles connections from up to 100000 different IPs
   QS_ClientEntries 100000
   # will allow only 50 connections per IP
   QS_SrvMaxConnPerIP 50
   # maximum number of active TCP connections is limited to 256
   MaxClients              256
   # disables keep-alive when 70% of the TCP connections are occupied:
   QS_SrvMaxConnClose      180
   # minimum request/response speed (deny slow clients blocking the server, ie. slowloris keeping connections open without requesting anything):
   QS_SrvMinDataRate       150 1200
   # and limit request header and body (careful, that limits uploads and post requests too):
   # LimitRequestFields      30
   # QS_LimitRequestBody     102400
</IfModule>

Result : most effective, stopped the atack after 1 second and stopt the attacker from using the same ip again

exampel log files afther attack :

[Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=350, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=350, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:07 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied (previously), QS_SrvMaxConnPerIP rule: max=50, concurrent connections=49, message repeated 0 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1    
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:07 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, message repeated 20 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=342, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:08 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=342, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:08 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=342, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=342, this connection=51, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:08 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:08 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers
[Fri Feb 14 13:37:08 2014] [error] mod_qos(031): access denied (previously), QS_SrvMaxConnPerIP rule: max=50, concurrent connections=47, message repeated 16 times, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:09 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=334, this connection=57, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:09 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=334, this connection=60, c=2a02:1800:1e1:6001::701:a1
[Fri Feb 14 13:37:09 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers, referer: http://code.google.com/p/slowhttptest/
[Fri Feb 14 13:37:09 2014] [error] [client 2a02:1800:1e1:6001::701:a1] request failed: error reading the headers, referer: http://code.google.com/p/slowhttptest/
[Fri Feb 14 13:37:09 2014] [error] mod_qos(034): access denied, QS_SrvMinDataRate rule (in): min=334, this connection=58, c=2a02:1800:1e1:6001::701:a1
@msmaromi
Copy link

msmaromi commented Jul 2, 2015

I am keep getting error Invalid command 'QS_SrvMinDataRate'. What am I missed?

@diegotricolor
Copy link

That's a bug for this directive in Apache 2.4

http://osdir.com/ml/general/2015-06/msg10083.html

@TechnologyClassroom
Copy link

I cannot submit a PR for a gist, but here is a patch that fixes most of the spelling errors:

spelling.patch

diff --git a/slow_http_attacks.md b/slow_http_attacks.md
index a6dd4e3..130d8f4 100644
--- a/slow_http_attacks.md
+++ b/slow_http_attacks.md
@@ -1,6 +1,6 @@
 Slow HTTP attacks are denial-of-service (DoS) attacks in which the attacker sends HTTP requests in pieces slowly, one at a time to a Web server. 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. When the server’s concurrent connection pool reaches its maximum, this creates a DoS. Slow HTTP attacks are easy to execute because they require only minimal resources from the attacker.
 
-Attack exploits the fact that most of modern web servers are not limiting the connection duration if there is a data flow going on, and with possiblity to prolong TCP connection virtually forever with zero or minimal data flow by manipulating TCP receive window size value, it is possible to acquire concurent connections pool of the application. Possibility to prolong TCP connection is described in several vulnerability reports: MS09-048, CVE-2008-4609, CVE-2009-1925, CVE-2009-1926 .
+Attack exploits the fact that most of modern web servers are not limiting the connection duration if there is a data flow going on, and with possibility to prolong TCP connection virtually forever with zero or minimal data flow by manipulating TCP receive window size value, it is possible to acquire concurrent connections pool of the application. Possibility to prolong TCP connection is described in several vulnerability reports: MS09-048, CVE-2008-4609, CVE-2009-1925, CVE-2009-1926 .
 
 Prerequisites for the successful attack are: - victim server should accept connections with advertised window smaller than server socket send buffer, the smaller the better – attacker needs to request a resource that doesn't fit into server's socket send buffer, which is usually between 64K and 128K. To fill up server socket's send buffer for sure, consider using HTTP pipelining (-k argument of slowhttptest)
 
@@ -43,7 +43,7 @@ Test Mitigation
     # From then, require a minimum data rate of 500 byte/s.
     RequestReadTimeout body=10,minrate=500
 
-Result : stopped the attac after 10 seconds , but allowed to atackker te retry after x time
+Result : stopped the attack after 10 seconds , but allowed to attacker te retry after x time
 
 ### mod_qos
 
@@ -65,9 +65,9 @@ Result : stopped the attac after 10 seconds , but allowed to atackker te retry a
        # QS_LimitRequestBody     102400
     </IfModule>
 
-Result : most effective, stopped the atack after 1 second and stopt the attacker from using the same ip again
+Result : most effective, stopped the attack after 1 second and stopped the attacker from using the same ip again
 
-exampel log files afther attack :
+example log files after attack :
 
     [Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1
     [Fri Feb 14 13:37:06 2014] [error] mod_qos(031): access denied, QS_SrvMaxConnPerIP rule: max=50, concurrent connections=51, c=2a02:1800:1e1:6001::701:a1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment