Login DoS — That requires simply sending a lot of specially crafted requests

3 months ago 65
BOOK THIS SPACE FOR AD
ARTICLE AD

Shriyans Sudhi

InfoSec Write-ups

Hi there,

I hope you are doing well.

In this article, I’ll discuss how I found a bug in a private program on HackerOne.

Theme image for the article
Let’s get started

Table of Contents

Program OverviewWhat is DoS, or Denial of Service?What happens on hitting the login button?How to send a long string to the server? (skip here if you know the above things, but a full read is recommended)Using a web application proxy to send a large requestOther places to look for this vulnerabilityReport TemplateIndustry: Software and AppsProgram type: PrivateMin Bounty: $50Max. Bounty: $500Response efficiency: 70%+

Denial of Service, or simply DoS, is a type of attack, in which the attacker sends multiple requests to the server to make the server crash or add a significant delay in the response timings for all the users.

This can lead to business loss as the customers of that website won’t be able to access the website and perform the actions, like buying things if it’s an e-commerce site, chatting with other people if it’s a public forum-like software, etc.

The request, that is sent to the server, is generally to cause DoS is generally specially crafted which adds a significant delay in the response timing.

This makes the server spend more resources on the attacker’s specially crafted request, and the genuine customer’s request will be allotted fewer resources, leading to a complete denial of service or causing a delay

In this section of the article, we will discuss what happens when you click the login button. This includes the processes that happen on the server side.

An image of a lock (sci-fi) to depict login
What happens on the server to get you logged in?

For any web application to prevent user passwords from being leaked in plaintext (not as hash) even after a data breach, companies store their password in the form of hashes.

These are some special functions, that convert strings of any length to a fixed length string.

You can convert a string into a hash, but you can’t do vice-versa.

Taking the example of MD5, you can convert the string “password” into MD5 hash “5f4dcc3b5aa765d61d8327deb882cf99”, but you can’t convert “5f4dcc3b5aa765d61d8327deb882cf99” directly into “password”

A graphical representation of what written above the image
You can convert string to hash, but not hash to string

Hashing is a complex process. It involves heavy calculation. Though the example demonstrated here, i.e. of MD5 hash function, takes less time as compared to other functions, it’s considered a bit insecure, but still it gives a good load on the CPU.

Getting back on to the point of what happens after clicking login.

A request is sent to the server, involving the username and the password specified by the user.

The password is either converted into a hash on the front end only (with the help of Javascript functions), or they are sent as plaintext (generally over HTTPS) to the server, which then calculates the hash of the password.

If the hash is being calculated on the front end only, then there are negligible chances that the server would be vulnerable to this attack.

For this attack to happen, the server must calculate the hash for the string provided

The longer the string is, the more time and CPU power it will consume to calculate the hash.

This means we have to send a long string to the application.

Now, once we know what happens on the backend, you should’ve figured out how to cause a DoS

How to send a long string to the server?

We just need to send a long string in the parameter for the password.

For this example, let’s consider the following request:-

POST /login
Host: www.target.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
--snip--
Content-Length: 123

username=*****&password=********

In the request given above, the parameter containing the password is password .

But before we send a long string, exactly how long is a long string?

Well, it depends upon the server. If the server has implemented some good hashing algorithms, then it will take more time, and vice-versa.

Generally, passwords of more than 10000 characters should be tested, by increasing the length of the string.

The following Python script can get your work done:-

for x in range(50000, 500000, 10000): #start:as it is , stop: as per your system's limit and considering the server load, step: value greater than 10K recommended
print("a"*x)

The above Python script will generate characters of length between 50K to 500K, with a difference of 10K between each string.

You can save the script, run it, and save the output of this to a file:-

python3 generate.py > lst.txt

This means the first line of the output will contain 50K characters, the second line will have 60K, and so on.

The timing can be tested by using web application proxies like Burp, ZAP, or Caido.

In my case, I’ve used caido, as it’s a very lightweight proxy compared to others.

Now, I’ll just fire up my web application proxy, which is Caido (not a promotion).

Logo of Caido
Logo for Caido

In the browser, I’ll open up the target, and head over to the login page, i.e. https://www[.]target[.]com/login

After filling in all the details on the login page, I’ll send the request for login, which in our example is POST /login to automate (intruder in Burp). After marking the payload position (the password parameter), I’ll set the payload type to “Simple List”, and I’ll load the output file for the above Python code

Screenshot from Caido for automate tab
Screenshot from Caido

Now, I’ll simply start the attack, and inspect the response timing for the requests

Screenshot of attack from Caido
Screenshot of attack from Caido

In the above screenshot, you can see that as the request ID is increasing, the response time is also increasing. This means that the server is vulnerable to this attack

Now, the attacker needs to just keep sending the requests, with a higher number of workers (at a very fast rate) and ultimately, it will cause a DoS on the server.

Note that to demonstrate impact on the server, you don’t need to cause a DoS. This is also out of scope for programs to cause an actual DoS (though they might accept DoS vulnerabilities). Just showing the difference in response time is enough.

If you’ve found a vulnerability at one place, there are chances that you can find the same vulnerability at other places on the web app.

An image of a web browser with a magnifying glass inspecting it
Other places to look for this vulnerability

Following are some more places that are worth checking if you’ve found this type of vulnerability:-

Sign-Up Page: An attacker can set a long password while signing upForgot Password: An attacker can set a long password after he clicks forgot passwordChange Password: In the account settings, an attacker can set a long password after entering the old passwordChange password (from the admin panel of the organization): An attacker, after creating a dummy company account can add a new user, and change his password to something long.## Summary
An attacker can cause DoS on the server by sending multiple login requests with long passwords

## Steps to reproduce
If you are using some GUI tool, make sure your system is capable enough of that. If not, please keep the character limit lower in the attack else your system will crash.

- Save the following Python script
```python
for x in range(50000, 500000, 10000): #start:as it is , stop: as per your system's limit and considering the server load, step: value greater than 10K recommended
print("a"*x)
```
- Adjust the limits as per your system
- Now, head over to <login_page_url>
- Capture the login request.
- Now, set the output of the Python script given above as the payload (in burp/ZAP/caido)
- Start replaying the request
- As the length of the payload increases, the response time also increases

If you want, you can also use the CLI, copy the request as cURL (right click > copy as cURL in all proxies), and modify the request as per your choice (remove garbage, etc). To make the length of the password big, use the following
```bash
curl .... -d "username=****&password=$(python3 -c 'print("a"*20000)')"
```

## Screenshot
<add screenshot from the intruder in burp>

## References
- [Possible denial of service when entering a loooong password - Nextcloud](https://hackerone.com/reports/840598)
- [No length on password - Imgur](https://hackerone.com/reports/1411363)

## Impact

An attacker can cause DoS on the system causing business losses

## Remediation
Before calculating the hash for the password on the server, make sure the length is less than what is set when storing the password

Read Entire Article