The HTTP Host header looks harmless, but when an application trusts it too much, it can lead to account hijacking, cache poisoning, SSRF, and even internal routing bypasses. This guide explains the attack in detail - including the part most people misunderstand: the attacker does not need DNS control.
What Is the Host Header?
Every HTTP/1.1 request includes a header called Host:
httpGET / HTTP/1.1
Host: example.com
Its purpose is simple: Tell the server which domain the client wants.
But thereโs a catch: The server blindly trusts whatever is written there. It never checks DNS to verify it.
Why Is This Dangerous?
Because many applications use the Host header to:
- Build absolute URLs
- Generate links in emails (verification, reset, confirmation)
- Do tenant selection in multi-domain setups
- Create redirect targets
- Form cache keys
- Detect โcurrent domainโ for business logic
If the attacker can change the header, they can influence all of these features.
How an Attacker Actually Exploits It (Step by Step)
This is the part that confuses people, so letโs make it crystal clear.
1. The attacker does NOT hack your DNS
- No domain spoofing.
-
No
/etc/hosts. - No Wireshark magic.
They just need your serverโs IP (which is usually trivial to find).
2. They send a request directly to your IP
Example:
http
Routing depends on the IP, not on the Host header, so your server accepts it normally.
3. Your server trusts the Host value
If your app does something like:
jsconst base = `https://${req.headers.host}`;
Then the password reset link becomes:
urlhttps://evil.com/reset?token=ABC123
4. You email that link to the victim
Your own server sends the poisoned link.
Victim sees:
Reset your password: https://evil.com/reset?token=ABC123
They click it.
5. Token goes straight to the attacker
Because evil.com is attacker controlled.
The attacker now owns the victimโs reset token and can change the password on the real site.
Other Attack Scenarios
1. Web Cache Poisoning
If your cache key includes the Host header:
httpHost: fake.com
The response gets stored under a weird key and may leak into the main cache path.
2. Internal Routing Bypass
Misconfigured virtual hosts sometimes route unexpected Host values to:
- Admin panels
- Internal dashboards
- Debug servers
3. SSRF via Host Header
Some apps make internal requests like:
bashcurl http://$HOST/status
If $HOST comes from the Host header, the attacker can force internal requests to:
- 127.0.0.1
- Internal admin services
- Metadata endpoints (e.g., AWS 169.254.169.254)
Why This Works (The Core Concept)
- HTTP does not validate the Host header: It doesnโt check DNS.
- Servers route based on IP, not Host: If the request reaches your IP, your app processes it normally.
- Any HTTP client can change the Host header: curl, Burp, Postman, or custom scripts.
Thatโs why the attack is trivially easy.
How to Prevent Host Header Attacks
1. Whitelist Allowed Hosts
Reject requests where Host is not one of your domains.
Node.js example:
jsconst allowed = ["example.com", "www.example.com"];
app.use((req, res, next) => {
const host = req.headers.host?.split(":")[0];
if (!allowed.includes(host)) return res.status(400).end();
next();
});
Go example:
goallowed := map[string]bool{
"example.com": true,
"www.example.com": true,
}
2. Never Generate URLs From req.headers.host
Use environment variables or configuration values.
Example:
envAPP_URL=https://example.com
3. Configure Reverse Proxies Correctly
Nginx:
nginxserver_name example.com www.example.com;
Disable wildcard hosts and avoid forwarding unvalidated Host headers upstream.
4. Enable Framework Features
Most modern frameworks already have protections:
-
Django โ
ALLOWED_HOSTS -
Rails โ
config.hosts - Symfony โ trusted hosts config
- Laravel โ trusted proxies
Use them.
5. Log Suspicious Host Values
Anything outside your known domain list should be logged and inspected.
Final Thoughts
HTTP Host header attacks seem simple, but they can break critical parts of your application - especially password resets, redirects, and multi-tenant logic. The trick works because web servers trust the Host value even though itโs 100% user-controlled.
Validate the header, avoid using it for important logic, and tighten your proxy configuration. Thatโs all it takes to block this entire class of vulnerabilities.
Album of the blog:




