ybugs.me

Host Header Injection: Understanding the Mechanics

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.


🔸 1. What is the HTTP Host Header?

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

Why do we need it? (Virtual Hosting)

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 .


🧨 2. The Vulnerability: Blind Trust

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.

The Core Assumption

Developers often assume the Host header is:

  1. Generated by the browser.

  2. Immutable (cannot be changed by the user).

  3. 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.


🧠 3. The Million Dollar Question: How does it even work?

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).

A. The “Envelope” vs. The “Letter”

B. The “Default Host” Loophole

When the server receives a request for Host: evil.com, it checks its internal list of websites.

  1. It does not find evil.com in its config.

  2. Fallback Behavior: Most servers are configured to serve a “Default Website” when they receive an unknown Host header.

  3. The Result: The server serves the victim application, but the application code still sees (and trusts) your malicious Host: evil.com header.


🧩 4. Root Causes: Why does it happen?

The vulnerability typically exists due to one of three failures:

A. Flawed Input Validation

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).

B. Component Confusion

Modern web stacks are complex. A Frontend (Reverse Proxy) and a Backend (App Server) often look at the request differently:

C. Default Server Behaviors

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.


📍 5. Where does it behave dangerously? (Attack Surface)

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

🛠️ 6. Attack Mechanics: How we inject

We don’t just “change the header.” We use specific techniques to trick parsers and bypass filters.

1️⃣ Basic Host Injection

Simply replacing the domain.

Host: attacker.com

Goal: See if the response reflects this domain (e.g., in a <link> tag or email).

2️⃣ Port Injection

Some validators check the domain but ignore the port.

Host: vulnerable-website.com:bad-stuff-here

Goal: Bypass validation or corrupt internal logging.

3️⃣ Ambiguous Requests (Duplicate Headers)

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.

4️⃣ Absolute URL Bypass

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.

5️⃣ Alternate Headers

If the main Host header is locked down, inject headers used by proxies.


🛑 Summary of Part 1