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 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 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, 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.

Attack scenario:

  • With burp intruder, I send 2 password reset links one for me and one for the victim.
  • The password reset link looks like this:*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:

Big thanks to Rajesh Ranjan and Ananda Dhakal for checking the draft of this article.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store