Before we dive into exploitation, we must understand the fundamental architecture that makes Host Header Injection possible. It is not just about changing a header; it is about exploiting the trust relationship between frontend components (Load Balancers, CDNs) and backend application logic.
Introduced in HTTP/1.1, the Host header is mandatory. It tells the web server which specific domain name the client wants to access.
Example:
GET /web-security HTTP/1.1
Host: portswigger.net
In the early days of the web, one IP address equaled one website. Today, a single cloud server or Load Balancer might sit in front of hundreds of websites.
This is called Virtual Hosting .
The Apartment Complex (IP Address): The physical location.
The Apartment Number (Host Header): Tells the server exactly which tenant (website) the request is for.
Host Header Injection is an attack that exploits unsafe usage or implicit trust in this header.
The vulnerability arises when an application blindly trusts this user-controllable input without validation.
Developers often assume the Host header is:
Generated by the browser.
Immutable (cannot be changed by the user).
Trustworthy for identifying the current domain.
The Reality: Tools like Burp Suite allow us to send any value we want. If the server uses this input to perform critical logic (like generating links or routing traffic), we can hijack that process.
If I change the Host header to evil.com, why doesn’t the request fail? How does it still reach the victim server?
This is the most common confusion. To understand this, we must distinguish between the Connection (Network Layer) and the Content (Application Layer).
The Connection (TCP/IP): When you send a request in Burp Suite, the tool connects to the Target IP you configured (e.g., 192.168.1.5). This is the address on the “envelope.” The packet arrives successfully because the IP is correct.
The Content (HTTP): Once the server opens the envelope, it reads the Host header inside.
When the server receives a request for Host: evil.com, it checks its internal list of websites.
It does not find evil.com in its config.
Fallback Behavior: Most servers are configured to serve a “Default Website” when they receive an unknown Host header.
The Result: The server serves the victim application, but the application code still sees (and trusts) your malicious Host: evil.com header.
The vulnerability typically exists due to one of three failures:
The most common cause is a lack of a whitelist. The server accepts any Host header provided by the client, even if it belongs to an attacker (evil.com).
Modern web stacks are complex. A Frontend (Reverse Proxy) and a Backend (App Server) often look at the request differently:
Frontend: Might route traffic based on the IP or the first Host header.
Backend: Might generate content based on the second Host header or the X-Forwarded-Host header.
Many frameworks (like PHP or Django) offer built-in variables (e.g., $_SERVER['HTTP_HOST']) to help developers build absolute URLs. These variables pull data directly from the untrusted request header.
The Host header is dangerous when used in these specific contexts:
| Component | Dangerous Behavior | Impact |
|---|---|---|
| Email Service | Generates password reset links using the header. | Account Takeover |
| Caching System | Uses the header as part of the “Cache Key”. | Cache Poisoning |
| Reverse Proxy | Uses the header to determine internal routing. | SSRF |
| Access Control | Trusts localhost headers implicitly. |
Auth Bypass |
We don’t just “change the header.” We use specific techniques to trick parsers and bypass filters.
Simply replacing the domain.
Host: attacker.com
Goal: See if the response reflects this domain (e.g., in a <link> tag or email).
Some validators check the domain but ignore the port.
Host: vulnerable-website.com:bad-stuff-here
Goal: Bypass validation or corrupt internal logging.
Sending two conflicting headers.
Host: vulnerable.com
Host: attacker.com
Goal: Trick the frontend into routing safely with the first header, while the backend processes the second malicious one.
Supplying the absolute URL in the request line.
GET [https://vulnerable.com/](https://vulnerable.com/) HTTP/1.1
Host: attacker.com
Goal: Exploit parsing discrepancies where the server trusts the Request Line for security but the Host Header for logic.
If the main Host header is locked down, inject headers used by proxies.
Concept: Servers host multiple sites on one IP (Virtual Hosting).
Flaw: Components blindly trust the Host header to generate links or route traffic.
Attack: We send requests to the valid IP but with a malicious Host header. The server processes our request using the malicious data.