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

Password Recovery Flow - Flowing Straight Into Attackers’ Hands

Sebastian Jeż

September 05, 2025

Introduction Password recovery mechanisms are one of the most crucial security components in any modern web application. A secure “Forgot Password” process ensures that users can recover access to their accounts without exposing themselves to unnecessary risks.

OWASP’s Forgot Password Cheat Sheet does a great job of outlining best practices for building safe and resilient recovery flows.

However, during a recent security assessment, we discovered that even when some of these measures were seemingly in place, an attacker could still bypass the protections and execute a successful brute-force attack against the password recovery codes.
Vulnerability Overview At first glance, the application appeared to implement stronger protections than typically encountered during security assessments. The recovery process relied on several mechanisms designed to secure the flow:

• Each password recovery flow generated a unique recovery_flow_token,
• Requests required a valid CSRF token,
• Session cookies tied each flow to a specific browser session.

It took us some time to identify the vulnerability, as the existing protections initially appeared difficult to bypass. At first glance, the recovery process looked solid: each request relied on a unique recovery_flow_token, and every submission required a valid CSRF token.

To automate the attack efficiently, we initially used Selenium. It simply simulated user interactions by opening the recovery page, entering the email address, “clicking” through the process, and capturing the tokens directly from the network logs. In reality, though, Selenium was not essential. Since it executes the same JavaScript as any standard browser, the entire process could just as well be replicated without it by analyzing the frontend logic and adjusting the exploit code.

That said, this approach is not guaranteed to work in every environment. Some applications heavily obfuscate their JavaScript or generate tokens using complex client-side computations, browser fingerprinting, or other mechanisms. In such cases, directly simulating the API calls might be a nightmare, and using Selenium or a headless browser would remain the more practical choice.
How the attack works: 1. Start a recovery flow
The attacker requests a password reset and receives a new recovery_flow_token and CSRF token.
2. Capture tokens and session data
Selenium is used to open the recovery page, submit an email address, and extract the tokens from network requests.
3. Send multiple code guesses
For each recovery flow, three random 6-digit codes are submitted.
4. Restart and repeat
After three attempts, a new flow is generated, and the process loops indefinitely.
Because there were no global rate limits, account lockouts, or CAPTCHA challenges, this approach made brute-forcing recovery codes both practical and efficient. Proof of Concept (PoC) Below is the original PoC script we used to demonstrate the vulnerability.
We anonymized sensitive details but kept the core logic intact. This PoC demonstrates that by constantly restarting recovery flows, an attacker can completely bypass per-session attempt limits and brute-force codes until the correct one is found Impact This vulnerability makes full account takeover possible if the attacker knows the victim’s email address.

Because the recovery code space is limited, an attacker could make the exploit highly efficient and potentially succeed within a few hours or, at most, a few days. Recommendations To mitigate this vulnerability, we recommend:

• Global rate limiting - apply restrictions across all flows, users, and IPs.
• Stronger recovery tokens - replace 6-digit numeric codes with long random strings or UUIDs.
• CAPTCHA integration - introduce verification after multiple failed attempts.
• Anomaly detection - monitor for mass recovery requests and trigger alerts on suspicious patterns.
Conclusion Even though the application used recovery_flow_token and CSRF tokens, the absence of global brute-force protections allowed attackers to bypass the password recovery security entirely.

Bruteforcing short recovery codes is feasible, cost-effective, and stealthy when no comprehensive safeguards are in place. Implementing stronger tokens, global rate limits, and effective monitoring is essential to protect user accounts.









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!