Application Level Denial of Service – A Comprehensive Guide

Application level Denial of Service attacks are designed to render systems unresponsive, denying the services for users. They are notoriously difficult to detect & prevent and underestimated. This comprehensive guide explains how to identify and remove the conditions necessary for DoS attacks.

Denial of Service attacks that bring down popular websites often involve thousands of hacked consumer devices and servers. While these attacks mainly aim to overwhelm the target system with traffic, in order to deny service to legitimate users, bugs at the Application Layer (Layer 7 in the OSI model) can have the same effect.

Application Level Denial of Service (L7 DoS) errors are often tough to identify and sometimes even tougher to prevent. This guide aims to highlight the different techniques that will help you find out what to look for and where DoS conditions may occur.

Table of Content

  1. Random Access Memory (RAM)
    1. Recursion
    2. Tricking an Application Into Allocating a Huge Amount of Memory
    3. Other
  2. Central Processing Unit (CPU)
    1. Recursion
    2. Abusing Resource-Intensive Operations
  3. Disk Space
  4. Exhaust Allocated Resources for a Single User
  5. Logic-Based Denial of Service
  6. Basic Tips and Tricks to Identify & Prevent Application DoS Attacks

Random Access Memory (RAM)

In order to function properly, applications need a certain amount of available RAM. While it’s possible to deal with the system not being able to allocate new memory, most of the time the application will either hang or crash, both of which will result in a DoS scenario.

Recursion

Recursion is a common reason for L7 DoS attacks. It refers to a procedure that causes itself to repeat over and over again. In most cases, this is a controlled process and a valid technique in programming. However, in the case of L7 DoS, it’s the result of a small set of instructions whose execution prompts vulnerable applications to enter a resource-intensive loop, with the specific purpose of exhausting their resources.

This table lists examples that involve a system’s volatile memory.

Recursive File Inclusion

What to look out for

Here is an example of PHP code:

include(‘current_file_name.php’);

PHP allocates new memory for each inclusion, and repeats the process until there is no memory left. When running the code in Command Line Interface (CLI) mode, there is no check to break this loop. However mod_php for Apache has a safety switch that aborts script execution if it detects too many repetitions. In addition, it throws an internal server error. However, a multithreaded script running on a single machine can query the page repeatedly, leading to the same end result – PHP running out of memory. This behaviour may also apply to other programming languages.

Where it is found

This kind of vulnerability can be found in places where a traditional Local File Inclusion (LFI) vulnerability might occur. However, because it doesn’t need to traverse directories and its PHP extension, it affects otherwise non-exploitable LFIs.

Zip Bombs

What to look out for

In the early 2000s, ZIP bombs were emailed to unsuspecting victims in order to crash their personal computers or mail servers. Ironically, this was often the fault of the system’s antivirus program’s automated extraction of the archive (in order to scan it), not that of the user opening it. Now, most antivirus vendors would either detect ZIP bombs or avoid extracting them completely. Briefly, some file compression algorithms work by replacing recurring patterns in the file with short references to a single occurance of the pattern. Let’s say that instead of writing ‘AAAAAAAAAAAAAAAA’, you could write ‘1-16-A’ to display the character ‘A’ sixteen times at position 1. Replace ’16’ with ‘999999999’, and you’ll understand why a relatively small file can consume all the RAM or disk space once extracted. One famous example of a ZIP bomb is 42.zip, which is just 42 kb in size, but increases to 4.5 petabytes (approximately the size of 1.125 billion MP3 files). Even though it is called a ZIP bomb, it can be applied to similar formats.

Where it is found

Web applications that allow you to upload compressed files, and extract the content for you, might be susceptible to such an attack, particularly if the application (or or the library that handles the decompression) fails to conduct a proper inspection of the deflated file.

Billion Laughs Attack

What to look out for

This attack is a classic example of a relatively small set of instructions that leads to the generation of a massive amount of data once it is parsed. This is how it works. A first, a single entity is created. In most available examples, it’s called lol and its sole content is the word ‘lol’. Then another entity is created, called lol1. This entity contains ten references to the first lol entity. The entity lol2 contains ten references to lol1 and so on. This is repeated several times. If the parser expands all the entities, it will reach size of 109 ‘lols’ – one billion laughs.

Where it is found

You may encounter this vulnerability wherever an application accepts input formatted as XML and parses it on the server side. Various examples are available online, one of them on the linked wikipedia page.

Tricking an Application Into Allocating a Huge Amount of Memory

Sometimes applications can decide how much memory they need to allocate just by looking at file headers or serialized strings. If an attacker manages to manipulate these indicators, the application can be tricked into allocating large chunks of memory with very little effort.

Deserialization Vulnerabilities

What to look out for

Deserialization is a delicate topic and you should generally not deserialize user supplied input using functions that are not explicitly recommended as safe alternative to raw deserialization functions. However, depending on their implementation, even those functions may contain bugs that lead to a DoS condition. It might be possible to pass a string to a deserialization function that instructs the parser to allocate large chunks of memory (for example by using repeating nested array definitions as seen in the linked paper about various PHP vulnerabilities). A wide range of programming languages with a similar functionality, in addition to PHP, can be vulnerable.

Where it is found

Deserialization vulnerabilities may be found everywhere user input is accepted. Most of the time you can see where serialized strings are accepted by using the application normally and intercepting the traffic with a tool like Fiddler.

Manipulating File Headers to Allocate Large Memory Chunks

What to look out for

The HackerOne example illustrates a hacker manipulating file headers to allocate large memory chunks. Using a 260px * 260px jpg file, the researcher manipulated the file header in order to make it appear as if the image was 64250px * 64250px in size. This relatively small file eventually led to a DoS condition on HackerOne, and apparently on the researcher’s local image viewer. This happened because the application allocated a large amount of memory, ran out of RAM, swapped to disk and eventually denied service altogether.

Where it is found

This vulnerability might be found in places where computation is performed on an input file, and where the size of the file is saved in its header. This might include images and video files, and other file formats.

Other

Reading Infinite Data Streams

What to look out for

Reading infinite data streams using an LFI can create a DoS condition, where there is no check on the maximum readable amount of data. On Linux, the first choice for a data source would be either /dev/zero (infinite stream of NULL-bytes) or /dev/urandom (infinite stream of random data). In both cases, enough memory would be allocated to crash the application.

Where it is found

This vulnerability can be found in places where a user can specify which data is either read from the file system or from a remote server. As mentioned above, on the local Linux system, /dev/zero or /dev/urandom are the prefered options. For remote files, this 1TB speed test file is a suitable target.

Central Processing Unit (CPU)

The CPU is responsible for the execution of the instructions you write into your program. Depending on the task, the CPU may have relatively little work to do; alternatively, it may require large amounts of computing power. Work-intensive tasks may even tie up all of the CPU’s resources and render the system unresponsive.

Recursion

Recursion is not only a matter of RAM. If the CPU is forced to repeat a resource-intensive task, it will stop responding to subsequent requests until the task is finished. There are a few attacks that abuse this fact.

reDoS

What to look out for

reDoS (Regular Expression Denial of Service) was put under the spotlight in 2016 when it caused stackoverflow.com to go offline for just over 30 minutes. It wasn’t the fault of an attacker, but a user who included 20,000 whitespace characters in a code snippet. According to the write-up, the regular expression was written in such a way that it forced the system to check the 20,000 character string in 200,010,000 steps (20,000 + 19,000, + … + 2 + 1). There are more details in both the OWASP page and the the Stackoverflow blog post, but other sites also provide a useful examination of the issue.

Where it is found

If a web application allows you to input your own regex code, it might be possible to execute the above-mentioned attack. In older versions of PHP, it might even lead to remote code execution.

SQL Injection Wildcard Attack

What to look out for

An SQL injection wildcard attack works in a similar way to a plain reDoS. The key difference is that it doesn’t just use the usual regular expression syntax, but employs so-called ‘wildcards’ that are used by databases to find data matching a specific description. These attacks can either be carried out using an (otherwise not vulnerable) search functionality, or via an attack vector, where it’s possible to execute SQL statements, for example with an existing SQL injection vulnerability.

Where it is found

Due to the nature of the vulnerability and the affected SQL functions, it can often be found in search functionality. To learn more about how such attacks are conducted, see the linked paper.

Fork Bombs

What to look out for

Fork bombs are processes that duplicate themselves over and over again until they use up all of the system’s resources. Both the CPU and the process table are affected. They acquired their name from the fork system call that they use. Perhaps the most commonly-known fork bomb is the following shell command: :(){ :|:& };:. This shows that fork bombs use recursion as the : function calls itself over and over again. Fork bombs are rarely used in web application attacks.

Where it is found

This attack would be conducted in a sandboxed environment that allows code execution of some sort, without giving an attacker access to sensitive data. Otherwise an attacker might decide to use the code execution for malicious purposes that are worse than a Denial of Service attack.

Abusing Resource-Intensive Operations

It is often possible for a user to instruct the server to execute a resource-intensive set of instructions. These don’t necessarily involve recursion. Instead, they are often CPU-hungry operations, that are either designed to be ineffective or require a large amount of computing power to carry out the instructions.

Abusing Password Hashing Functions

What to look out for

Why would anyone purposefully design a set of instructions that take a long time to execute and require a lot of computing power? One possible application is abusing password hashing functions. The reason is simple. Modern password hashing functions are designed to be ineffective, which is achieved by so-called ‘key stretching‘. They need a lot of time and resources to return the desired output. This is intentional because it slows down attackers that are trying to find the passwords belonging to those hashes. This property distinguishes these algorithms from the ones used in other kinds of hashing functions. These are generally designed to quickly return checksums for large files.

Where it is found

Attackers could abuse this fact to achieve a DoS attack, if they submitted a huge amount of long passwords to the hashing function. Depending on the cost factor and server hardware, this could easily lead to a DoS.

Headless Browser SSRF

What to look out for

Headless browsers are sometimes used to visit user-supplied websites and easily render the DOM, in order to take a screenshot of the page that was submitted. There are several vulnerabilities that can arise when using such a setup, such as the disclosure of local file contents or a classical Server Side Request Forgery vulnerability that allows interaction with services behind your firewall. But even if those obvious flaws are considered, it is still possible to exhaust the server’s resources by instructing it to parse JavaScript code that was placed on your website. This might lead to a DoS condition.

Where it is found

Code that leads to a high CPU load might be JavaScript-specific reDoS or even cryptocurrency mining, the latter being limited by the hardware in use and connection timeouts.

Disk Space

Most programs need more than simply a CPU and volatile memory in order to operate. They also need to be able write to disk so that they can store information. The generated files are used for caching, configuration or in order to write to disk in case RAM space is tight. Programs may crash or act unpredictably and whole systems can become unstable.

Uploading Large Files

What to look out for

Arguably the most obvious way to fill a system with data is by uploading large files to the server. If the application doesn’t apply proper rate-limiting and size checks for its file upload functionality, an attacker can upload random junk data to the system until it can no longer store any more data. This either makes the file upload functionality fail for legitimate users, or can make the entire system unstable.

Where it is found

Profile picture upload functionality, while ubiquitous, is fortunately unsuitable for this type of attack because previous uploads are deleted once a user uploads a new image. Instead, this can be achieved by uploading files in private messages or in bug reports or help desk applications.

Generating a Huge Amount of Databases or Log Files

What to look out for

In the early days of non-relational databases, NoSQL injections could easily be used to execute arbitrary JavaScript on the vulnerable server. Nowadays however, the available JavaScript functions are greatly reduced and run in a sandboxed environment. Nonetheless it’s still possible to wreak havoc with the whitelisted JavaScript functions, should an attacker achieve code execution. It’s possible to either use one of the above-mentioned techniques to exhaust all the available RAM or utilize reDoS to bind all the available CPU resources. However, it’s also possible to write into the log files using server side JavaScript. This results in generating a huge amount of databases or log files, if an attacker writes to it in a continuous loop.

Where it is found

Often this attack can be conducted either by directly searching for server side JavaScript injections or by using features such as MongoDB’s $where.

Arbitrary File Deletion

What to look out for

The deletion of arbitrary files is a completely different DoS approach. Using an arbitrary file deletion vulnerability, an attacker can remove data that is necessary for the application in order to work correctly. This may include removing configuration files or even script code in order to deny service to legitimate users.

Where it is found

Where to find such a vulnerability is highly application-specific. But it often involves directory traversal.

Exhaust Allocated Resources for a Single User

On applications or services that allow multiple users, resources are limited and have to be allocated in a fair way. Users can only use a certain amount of available space. It’s easy for attackers to fill that space, and deny service for one specific user.

Email Bomb

What to look out for

Users are regularly allocated a small amount of space for their inbox. The goal of an Email Bomb is to flood a user’s inbox to the point where all available space is exhausted, and subsequent (legitimate) emails bounce.

Where it is found

Attackers can abuse this flaw by sending a moderately large amount of emails with large attachments. After a short time, the mailbox is full and new emails are rejected. While it should be easy to fill a victim’s inbox if space is tight, there is an attack called List Linking that addresses targets with larger inboxes. An attacker registers the victim for various, high-frequency mailing lists and lets them spam the inbox.

Free Website Restrictions

What to look out for

Some web hosts allow only a certain amount of requests per day for users on free subscriptions. If the amount of requests exceeds the maximum limit, the page becomes unavailable for a certain amount of time, except if the user pays for a subscription.

Where it is found

It is relatively easy to trigger this maximum limit by querying the site in a continuous loop, using a tool like cURL. There are only two lines needed in order to create a valid HTTP 1.1 request.

Cash Overflow

What to look out for

A similar approach is called Cash Overflow. Instead of targeting disk space, RAM or the CPU, the attack aims to raise the bill for a service up to the point where it exceeds the allocated amount of money. Should the owner of the website be unable to pay the bill or if automatic payment fails, the service will be terminated – effectively leading to DoS. This can happen if an external service is used that bills the user a certain amount of money per request.

Where it is found

Since these requests are generally inexpensive, an attacker needs to generate huge amounts of traffic in order to achieve DoS.

Logic-Based Denial of Service

A DoS for specific users might have legitimate reasons – either to enforce rate limiting or to deny access for malicious users. Like every other piece of code, this functionality can contain bugs. And sometimes the application can be tricked into denying service to specific, legitimate users.

X-Forwarded-For

What to look out for

Hackers can use a well-known trick, to overcome IP-based rate limiting or blocks, if the application incorrectly uses headers like X-Forwarded-For in order to determine users’ IP addresses. It’s easy to forget that this flawed implementation also opens the door for a DoS attack, if the IP address of a legitimate user is used instead of a random one for example. Attackers may constantly trigger rate limiting, with an X-Forwarded-For header containing the victims’ IP address. If victims can’t mask or change their IP address, they are denied service for the duration of the attack.

Where it is found

This flaw can be found on any application protected by a web application firewall (WAF), or any application that applies rate limiting as long as either of these measures can be bypassed using X-Forwarded-For.

Web Application Firewalls

What to look out for

Many web application firewalls can be configured to block users that send malicious requests, for a certain amount of time. Those requests may contain specific, special characters like backticks and single quotes or blocked keywords such as script and passwd. An attacker can set up a page that will send such requests to a WAF-protected website, or in other words, trigger the DoS condition through cross-site request forgery (CSRF). Once it sees the request coming from the victim’s IP, it will automatically block it for a certain amount of time. The same works if the attacker is able to set a cookie with a blocked keyword.

Where it is found

This can be found wherever a WAF is protecting the application and users are blocked in the event of malicious keyword detection.

Wasting the Available Password Attempts

What to look out for

Preventing attackers from bruteforcing the credentials of legitimate users is difficult. Often this problem is solved using a captcha. But sometimes developers resort to blocking the account after a certain amount of wrong login attempts. If an attacker wastes all of the login attempts for a specific user, either accidentally while brute forcing or on purpose, the affected user will be denied access as well.

Where it is found

This vulnerability can arise wherever there is a limited amount of password attempts per user, rather than per IP address or session. Sometimes applications will send a link to the victim in order to unblock the account again. This should be tested to avoid false positives.

Cookie Bombs

What to look out for

If an application endpoint allows the generation a big amount of cookies (a cookie bomb) with different names, an attacker can instruct the victim’s browser to store and send enough cookies in order to exceed the allowed request size. This will eventually lead to a denial of service condition that can only be fixed by deleting all the malicious cookies.

Where it is found

As mentioned above, the application must have cookies with different names in order for this to work. The attack would be triggered via CSRF.

Basic Tips and Tricks to Identify & Prevent Application DoS Attacks

  • You don’t generally need to receive the request responses when conducting a DoS attack. If you want to test for Denial of Service conditions yourself, we recommend that you use HEAD instead of GET requests where possible, or use the Range header with a value of ‘bytes=0-0’
  • Certain methods of error handling are resource-intensive. If you encounter a verbose error, this might indicate that there is a large amount of computing power involved. For example, stack traces are known to be resource-intensive.
  • A small amount of input that leads to an exceptionally large return value is always a good place to look for DoS, especially if recursion is involved.
  • Whenever you encounter a DoS error, you should consider whether this is the worst impact the vulnerability might have. If there is an Local File Inclusion, try to read sensitive information rather than recreating a DoS. And if you can issue a limited set of commands, try to escape from the sandbox and turn it into a full RCE, instead of wasting the system’s resources. This helps to more accurately calculate the risk for the developers to which you report the flaw. Should you submit your findings to a bug bounty program, it is also likely to lead to a more lucrative payout.

If we neglected to mention something you think is important, or if you have another idea about where a DoS condition might occur, please tweet us your suggestions and tricks.

Sven Morgenroth

About the Author

Sven Morgenroth - Senior Security Engineer