Web Application Denial of Service Next Level
In this tutorial we are going to talk on how to cause maximum down time (including operational recovery processes) in anything that uses the word Web, this is also known as a Denial o Service Attack. Using this knowledge for malicious purposes is not something I am recommending or approve and I have zero accountability on how you use this knowledge. This is the reason I am providing also with countermeasures on the end of the post.
What Is The Landscape
In the past we have seen many Denial of Service attacks, but most of them were not very sophisticated. A very good example would be the Low Orbit Ion Cannon (LOIC). LOIC performs a DoS attack (or when used by multiple individuals, a DDoS attack) on a target site by flooding the server with TCP or UDP packets with the intention of disrupting the service of a particular host. People have used LOIC to join voluntary botnets.
All these attacks as stated in previous post do not really take advantage of the 7th layer complexity of the Web and therefore are not so effective as they could be. A very good post exists in the Cloudflare blog named Famous DDoS Attacks .
A few of the famous attacks are:
- The 2016 Dyn attack
- The 2015 GitHub attack
- The 2013 Spamhaus attack
- The 2000 Mafiaboy attack
- The 2007 Estonia attack
In order to improve or understand better what is possible while conducting a DoS attack, we have to think like a Web Server, Be a Web Server, Breath like a Web Server!!
Well what does a server breath? But of course HTTP, so what if we make the Web Server start breathing a lot of HTTP/S, that would be amazing.
This is how we can over dose with HTTP a web server:
- HTTP Connection reuse
- HTTP Pipelining
- Single SSL/TLS handshake
HTTP connection reuse
HTTP persistent connection, also called HTTP keep-alive, or HTTP connection reuse, is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair.
The newer HTTP/2 protocol uses the same idea and takes it further to allow multiple concurrent requests/responses to be multiplexed over a single connection.
HTTP 1.0, connections are not considered persistent unless a keep-alive header is included, although there is no official specification for how keepalive operates. It was, in essence, added to an existing protocol. If the client supports keep-alive, it adds an additional header to the request:
Then, when the server receives this request and generates a response, it also adds a header to the response:
Following this, the connection is not dropped, but is instead kept open. When the client sends another request, it uses the same connection. This will continue until either the client or the server decides that the conversation is over, and one of them drops the connection.
In HTTP 1.1, all connections are considered persistent unless declared otherwise. The HTTP persistent connections do not use separate keepalive messages, they just allow multiple requests to use a single connection.
If the client does not close the connection when all of the data it needs has been received, the resources needed to keep the connection open on the server will be unavailable for other clients. How much this affects the server's availability and how long the resources are unavailable depend on the server's architecture and configuration.
Yes dear reader I know what are you thinking, how can you the humble hacker, the humble whitehat reader can use this knowledge to bring down your home web server for fun? Well there are good news.
In Python there are various functions provided for instantiating HTTP keepalive connections within urllib3 library, such as ConnectionPools.
Here is a code chunk to look through:
- keep_alive – If True, adds ‘connection: keep-alive’ header.
- accept_encoding – Can be a boolean, list, or string. True translates to ‘gzip,deflate’. List will get joined by comma. String will be used as provided.
- user_agent – String representing the user-agent you want, such as “python-urllib3/0.6”
- basic_auth – Colon-separated username:password string for ‘authorization: basic ...’ auth header.
HTTP pipelining is a technique in which multiple HTTP requests are sent on a single TCP (transmission control protocol) connection without waiting for the corresponding responses. The technique was superseded by multiplexing via HTTP/2, which is supported by most modern browsers.
See following diagram for pipeline :
HTTP pipelining requires both the client and the server to support it. HTTP/1.1 conforming servers are required to support pipelining (Pipelining was introduced in HTTP/1.1 and was not present in HTTP/1.0). This does not mean that servers are required to pipeline responses, but that they are required not to fail if a client chooses to pipeline requests. Interesting behavior!!!!!!!!!
Note: Most of the servers execute requests from pipelining clients in the same fashion they would from non-pipelining clients. They don’t try to optimize it.
Again, yes dear reader I know what are you thinking, how can you the humble blackhat hacker, the humble hacktivist reader can use this knowledge to bring down your home web server for fun? Well there are more good news.
Some Python frameworks do support HTTP/2 aka HTTP pipelining , Mouxaxaxa. As of late 2017 there are two Python frameworks that directly support HTTP/2, namely Twisted and Quart with only the latter supporting server-push.
Quart can be installed via pipenv or pip:
This requires Python 3.7.0 or higher (see python version support for reasoning).
A minimal Quart example is:
Also another library that supports Python HTTP/2 connectivity is hyper. hyper is a Python HTTP/2 library, as well as a very serviceable HTTP/1.1 library.
To begin, you will need to install hyper. This can be done like so:
From the terminal you can launch a request by typing:
Used in this way, hyper behaves exactly like http.client classic Python client. You can make sequential requests using the exact same API you’re accustomed to. The only difference is that HTTPConnection.request() may return a value, unlike the equivalent http.client function. If present, the return value is the HTTP/2 stream identifier.
In HTTP/2, connections are divided into multiple streams (due to pipelining). Each stream carries a single request-response pair. You may start multiple requests before reading the response from any of them, and switch between them using their stream IDs.
Note: Be warned: hyper is in a very early alpha. You will encounter bugs when using it. If you use the library, provide feedback about potential issues and send to the creator.
By dramatically speeding up the number of payloads per second send to the server we increase the chance to crash the system for the following reasons:
- Multiple HTTP/2 connections sending requests such as the following would cause significant resource allocation, both in the server and the database:
- File upload requests, with large files to be uploaded.
- File download requests, with large files to be downloaded.
- POST and GET requests containing exotic Unicode Encoding e.g. %2e%2e%5c etc.
- POST and GET requests while performing intelligent fuzzing.
- Enforcement of single SSL/TLS Handshake:
- Not much to be said here. Simply enforce a single TLS handshake if the malicious payloads are going to consume more resources than the handshake it self. This will cause the server to consume resources.
Note: Such type of an attack can also be used to as a diversion to hide other type of attacks, such as SQLi etc.
The diagram below demonstrates where potentially system is going to crash first:
Other Uses of The This Tech
We can use this knowledge to perform the following tasks:
- Optimize Web App Scans
- Optimize directory enumeration
- Optimize online password cracking on Web Forms
- Optimize manual SQLi attacks
There are some tools out there that make use some of the principles mentioned here:
- Turbo Intruder - https://github.com/PortSwigger/turbo-intruder - Turbo Intruder is a Burp Suite extension for sending large numbers of HTTP requests and analyzing the results. It's intended to complement Burp Intruder by handling attacks that require exceptional speed, duration, or complexity.
- Skipfish - https://code.google.com/archive/p/skipfish/ - Skipfish is an active web application security reconnaissance tool. It prepares an interactive sitemap for the targeted site by carrying out a recursive crawl and dictionary-based probes.
Things to do to avoid this type of attacks are:
Things to do to avoid this type of attacks are:
- Firewall HTTP state filtering rules
- Firewall HTTPS state filtering rules
- Firewall HTTP/2 blockage - Although not recommended
- WAF that checks the following things -
- User Agent - Check for spoofing the agent
- Request Parameters - Check for fuzzing
- Request size check.