How I was able to take over any account via the Password Reset Functionality.
Hey, This is my first writeup and I will talk about an account takeover that I found in May on a vulnerability disclosure program. Let’s assume https://target.com is the target since the program does not allow public disclosure.
The first thing I do when I start hunting on a new target is navigating the entire application to understand it (What does it do, The main functionality, Technologies used..), After that, I test the Password Reset Functionality.
How I test for bugs in password reset functionality:
- I change the host when sending the request.
- I look for the token in the response.
- Tamper with id/email params if available (Add them if not).
- I collect a good number of tokens and analyze them by asking questions like this:
- Can it be decoded?
- Is it bruteForcable?
- Is it predictable?
- What part of the token remains the same?
So, when testing the password reset functionality on target.com the first 3 tests failed no host header injection, no token leakage as well there is no ID/Email params. However, after collecting about 8 tokens I figured out that there are 2 parts of the token that remains the same and the other 2 parts change every time.
Although the part that changes every time is smaller than the static part I still cannot brute-force the token since the orange part contains letters/numbers and they are random. So I saved the tokens, took some notes, and moved to test other functionalities.
After, 3–5 days while reading my notes I wanted to give it another shot. So, I opened https://target.com, made another account, and manually I sent 2 requests to reset the password(One to my 1st account, and one to my 2nd account). Got the tokens, Copied/pasted them on my bloc note, and to my surprise, the tokens differ only in the last 3 characters.
It seems like the shorter the duration between the requests the more the tokens are similar.
You would ask why when I first collected the tokens I did get 5 different characters. It’s because I was sending 1 request at a time, save the token and repeat again.
Now we have 2 tokens that differ only in the last 3 characters but still, they are random. Which makes it hard If not impossible to brute-force. So, I thought maybe if I send them with burp intruder I can get better results since intruder sends requests faster than my hands :D. I fired up BurpSuite, captured the request, send it to the intruder:
- Payloads: My 2 accounts emails.
- Threads: 20
- URL-Encode: OFF
Now, after configuring burp intruder I launched the attack and boom I got 2 tokens that differ only in the last character.
- With burp intruder, I send 2 password reset links one for me and one for the victim.
- The password reset link looks like this: https://exmaple.com/reset/5ec6ea8d546ca610758297e*2*
- By design, if I visit a password reset link with an invalid token the application won’t display the form to change the password. So, I only have to change the last number and check if the form is there.
Also, I found an API endpoint from which I can enumerate email addresses, which will make it easier for an attacker.
Finally, I reported the bug. And even though it was a VDP they rewarded me with a bounty!
- Take notes so when you learn something new or you get new ideas you can test them.
- Always think outside the box, ask good questions.
My Twitter: https://twitter.com/Fatnass1F1ras