This website uses cookies

To provide the highest level of service we use cookies on this site.
Your continued use of the site means that you agree to their use in accordance with our terms and conditions.

Insights

Low entropy of password reset token leads to account takeover

Kamil Szczurowski

August 22, 2025

Introduction During a recent security audit, something related to password reset functionality caught my attention. It appealed that password reset tokens generated for a given account in the same second were always the same. Such behaviour suggested that password reset token is generated from a few factors, but only one of them – time wasn't static. Discovery and verification The first sign of weak password reset token entropy was the fact that tokens generated for the same user during the same second were the same. That meant that time was the only factor that changed in the token itself. Other factors were always the same and either static or related to a given user. With that discovery, I began investigating further how the token could be constructed.

The first step was to obtain a valid timestamp that was used by the web server. In order to do that, I sent the following HTTP request that requested password reset action: Server confirmed that password reset token was sent and returned date in its header: The date returned by the server will be used in further steps – it would be the one used in the process of generating the password reset token.

The reset token received in the e-mail was: The reset token was a result of a MD5 hashing function, so the first thing that I've checked was conjunctions of timestamp/date with just an e-mail address. Results unluckily weren’t positive – generated token must've had at least a third factor. An example of some tried conjunctions are shown below: Knowing that there's a third unknown factor, we'll use "advanced password recovery" software, which is hashcat. Provided that we know part of the original string, we'll use a combinatory attack mode that will combine two dictionaries – the first dictionary will consist of known permutations of date and e-mail address, the second will be just a standard dictionary used to break hashes (in this example rockyou.txt). The final command is presented below: After running the command, I noticed that hashcat successfully broke the hash: It's visible that third factor was just a word secret.

The tested application creates a token from three factors – user's e-mail address, time of password reset request response and pepper (which is a secret added to an input during hashing with a cryptographic hash function). In this case, developers choose secret to be a dictionary word, which is fairly easy to crack.

In order to verify that the vulnerability was identified correctly and identified password reset token structure is correct, I tried to exploit the whole process and gain access to my test account, by generating new password reset token and creating it from scratch.

First, I issued a standard password reset request: Then I copied the date from the response and transformed it into timestamp: After that, I created my own token and used MD5 hash function: The next step was verifying whether I will be able to successfully reset password with created token: Server responded with confirmation of password reset – confirming that vulnerability was properly identified and can be easily exploited: Server responded with confirmation of password reset – confirming that vulnerability was properly identified and can be easily exploited: The last step was doing the same thing, but with the admin's account. I requested password reset for an application admin account and was able to successfully reset its password – gaining the highest possible privileges in the application from an unauthorized user. Recommendations When generating password reset token ensure that generated tokens or codes are: • Randomly generated using a cryptographically safe algorithm,
• Sufficiently long to protect against brute-force attacks,
• Stored securely,
• Single use and expire after an appropriate period.









Next Pentest Chronicles

When Usernames Become Passwords: A Real-World Case Study of Weak Password Practices

Michał WNękowicz

9 June 2023

In today's world, ensuring the security of our accounts is more crucial than ever. Just as keys protect the doors to our homes, passwords serve as the first line of defense for our data and assets. It's easy to assume that technical individuals, such as developers and IT professionals, always use strong, unique passwords to keep ...

SOCMINT – or rather OSINT of social media

Tomasz Turba

October 15 2022

SOCMINT is the process of gathering and analyzing the information collected from various social networks, channels and communication groups in order to track down an object, gather as much partial data as possible, and potentially to understand its operation. All this in order to analyze the collected information and to achieve that goal by making …

PyScript – or rather Python in your browser + what can be done with it?

michał bentkowski

10 september 2022

PyScript – or rather Python in your browser + what can be done with it? A few days ago, the Anaconda project announced the PyScript framework, which allows Python code to be executed directly in the browser. Additionally, it also covers its integration with HTML and JS code. An execution of the Python code in …

Any questions?

Happy to get a call or email
and help!