ModSecurity Advanced Topic of the Week: Mitigation of 'Slow Read" Denial of Service Attack

Slow-Read DoS Attack Background

Another tweak in the ongoing "Slow" DoS attacks has emerged this week. The previous Slow DoS attacks focuses on methods of slowing down the rate of request data sent to the target web server. This time, the attack centers on a method of slowing down the rate at which the client (attacker) is able to consume the response data sent back by the web server - hence the name "Slow Read" DoS.

It is rather serendipitous as I actually had the same attack scenario in mind for some time but never got around to develop working exploit code. So a hat tip to Sergey Shekyan as we have seen in the security space that theoretical exploits fall on deaf ears and that you need working proof of concept code to get people to listen.

For those of you familiar with the old LaBrea Tarpit app for slowing down network based worms, this is somewhat of a reverse approach. Instead of the defender (LaBrea) sending back a TCP Window size of 0 to the attacker (worm) which would force the TCP client to wait for a period of time before resubmitting, in this scenario the attacker is the one forcing the web server to wait. After sending in the request, the client responds with TCP window sizes that are much smaller than normal. This forces the web server to queue the response a break it up into smaller chunks that the client will accept.

For further visual evidence, here is a screen shot of the Server-Status page right when the attack is stopped:

Notice that all of the threads are in a "W" Sending Reply state.

Mitigating Slow-Read DoS Attacks with ModSecurity

ModSecurity v2.6 introduced a new directive called SecWriteStateLimit, which will place a limit on the concurrent number of threads (per IP address) in a SERVER_BUSY_WRITE state. This was originally created to help mitigate the Slow Request Body DoS attacks as Apache moves these threads into this state when it is reading request body payloads. Well, as it turns out, when Apache is sending response body data back to a client, it too moves the threads into the SERVER_BUSY_WRITE state. This means that we can use the ModSecurity SecWriteStateLimit to set an upper threshold of concurrent threads (per IP address) in this state. If this threshold is met, then new threads over this limit will be terminated. The end result is that an attacker will not be able to tie up all available threads and other clients will be able to access the web server.

For testing purposes, the following ModSecurity directive was added to the configuration:

SecWriteStateLimit 100

The same slowhttptest test was then run and the Apache Server-Status page looked like this during the attack:

Notice that there is now a limit of ~100 concurrent connections (per IP address) in the W state and that the other threads are open and able to process new requests.

During the attack, the Apache error_log showed these error message from ModSecurity's SecLimitWriteState directive: