Password Reset Token Leakage via Host Header Poisoning (Real Bug Bounty Case Study)
Introduction
Password reset functionality is one of the most critical components in any web application. If it is not properly secured, it can lead to full account takeover and compromise of user accounts.
In this case study, I describe a real-world vulnerability I discovered in a bug bounty program where the password reset flow was vulnerable to Host Header Poisoning, allowing manipulation of password reset URLs.
For responsible disclosure, the target has been anonymized as target.com.
Vulnerability Overview
Host Header Poisoning occurs when a web application improperly trusts the Host header provided by the client.
By manipulating this header, an attacker can influence how the application generates absolute URLs, including password reset links sent via email.
In this case, the application directly used the Host header when generating password reset links. This allowed an attacker to inject a malicious domain and control the reset URL sent to users.
As a result, password reset links were generated using an attacker-controlled host instead of the legitimate domain.
Business Impact
This vulnerability can lead to serious security consequences:
- Full Account Takeover (via password reset manipulation)
- Password reset link redirection to attacker-controlled domains
- Phishing attacks using trusted email flows
- Unauthorized account access
- Loss of user trust and reputational damage
Since password reset flows are part of authentication trust boundaries, any manipulation in this process is considered high to critical severity depending on implementation.
Attack Scenario (Real-World Execution)
In my actual proof of concept, I used an Ngrok tunnel as an external interaction endpoint to observe how the application generated password reset links.
The attack flow was:
- I initiated a password reset request for a valid account email
- I intercepted the HTTP request using Burp Suite
- I modified the
Hostheader to an attacker-controlled Ngrok domain - I forwarded the request to the server
- The application generated a password reset link using the modified Host header
- The password reset email contained a link pointing to the attacker-controlled domain
- Opening the link confirmed that the reset flow was influenced by the manipulated Host header
This confirmed that the application relied on user-controlled Host headers for generating sensitive URLs.
Steps to Reproduce
- Navigate to the “Forgot Password” page
- Submit a valid registered email address
- Intercept the request using Burp Suite
- Modify the Host header to an attacker-controlled domain (e.g., evil.com or Ngrok URL)
- Forward the request
- Check the password reset email received by the account
- Observe that the reset link contains the modified Host instead of the legitimate domain
- Open the reset link and confirm the password reset flow is based on the manipulated Host header
Additional Header Manipulation Testing (Supporting Analysis)
During testing, I explored multiple Host-related parsing behaviors to understand how different components interpret HTTP headers.
These tests were performed to assess potential alternative attack vectors. However, only direct Host header manipulation was effective in this case.
1. Duplicate Host Headers
try to duplicate the host and put the attacker domain first
Host: attacker.com
Host: target.com
then try to duplicate the host and put the original domain first then in the second host put the attacker domain
Host:target.com
Host:attacker.com
Get Dr Ridox’s stories in your inbox
Join Medium for free to get updates from this writer.
Some systems may interpret the first or last value differently, depending on infrastructure.
2. X-Forwarded-Host Injection
Host: target.com
X-Forwarded-Host: attacker.com
Some reverse proxies may prioritize this header for URL generation.
3. Alternative Proxy Headers
Forwarded: host=attacker.com
X-Original-Host: attacker.com
Different frameworks may interpret forwarded headers differently.
4. Malformed Host Values
Host: attacker.com:target.com
Improper parsing may lead to ambiguity in hostname resolution.
Additional Observation: JSON Array Input Handling (Separate Finding)
During testing, I also observed how the backend handles JSON input when multiple values are provided for a field that expects a single value.
This is a separate input validation observation and is not directly part of the Host Header Poisoning vulnerability.
Normal Request
{
“email”: “victim@gmail.com”
}
Modified Request
{
“email”: [
“victim@gmail.com”,
“attacker@gmail.com”
]
}
Why This Matters
This tests whether the backend enforces strict schema validation for authentication-related fields.
In secure implementations, the system should:
- Enforce strict string type validation
- Reject arrays or multiple values
- Prevent ambiguity in identity processing
What Can Go Wrong in Weak Implementations
- Iteration over multiple values instead of rejection
- Inconsistent selection of first/last value
- Data normalization inconsistencies
- Authentication logic bypass in complex flows
Security Relevance
While this does not directly contribute to Host Header Poisoning, it may become relevant in sensitive workflows such as password reset, where:
- Input affects recipient selection
- Multiple processing paths exist
- Validation differs across components
Key Takeaway
User-controlled headers must never be trusted for generating security-critical URLs such as password reset links.
Root Cause
- Trusting user-controlled Host header
- Lack of canonical domain enforcement
- Improper reverse proxy configuration
- No server-side base URL validation
Proof of Concept (Conceptual)
Host: attacker-ngrok-domain.com
Result:
https://attacker-ngrok-domain.com/reset-password?token=XXXX
Expected:
https://target.com/reset-password?token=XXXX
This mismatch allowed external control over password reset link generation.
Final Thoughts
Host Header Poisoning is often underestimated, but when it affects password reset flows, it becomes a critical authentication vulnerability.
This issue demonstrates how a single trust failure in HTTP headers can escalate into a full account takeover scenario.







