Sitemap
Unknown KP

Unknown KP

Host Header Injection

11 min readJun 16, 2026

--

A practical guide covering the vulnerability, real-world impact, bypass techniques, and a step-by-step lab walkthrough.

1. What is the Host Header?

When your browser makes an HTTP request, it does not just send a request path — it also sends a set of headers that provide context about the request. One of the most fundamental is the Host header.

The Host header tells the web server which domain the client is trying to reach. It was introduced in HTTP/1.1 (RFC 7230) to solve a specific problem: a single server handling traffic for multiple websites. Without the Host header, a server running example.com, shop.example.com, and blog.example.com on the same IP address would have no way to distinguish which site a request was intended for.

A typical HTTP request looks like this:

GET /account HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html

The server reads Host: www.example.com, identifies which virtual host to route the request to, and responds accordingly. This mechanism underpins nearly every shared hosting environment, cloud deployment, and reverse proxy setup on the modern internet.

What makes the Host header security-critical is that servers frequently use its value to perform application logic — building password reset links, generating email content, constructing redirects, setting CORS policies, and even making server-side HTTP requests. If that value can be manipulated by an attacker, all of those downstream operations become attack vectors.

2. What is Host Header Injection?

Host Header Injection is a vulnerability that occurs when a web server or application uses the value of the HTTP Host header in its logic without validating that the value actually matches the server’s intended domain.

Because the Host header is sent by the client — meaning the browser, or in an attacker’s case, a tool like Burp Suite — it can be set to any arbitrary value. If the application trusts the Host header as authoritative and uses it to build URLs, links, or server-side requests without checking it against a whitelist of known-good values, an attacker can supply a malicious domain and trick the application into using it.

The attack is not about injecting content into the page like XSS. It is about injecting a controlled value into a trusted position in the application’s own internal logic — one the application then acts upon.

A simple illustration: an application generating a password reset email constructs the link like this on the server side:

php

$reset_link = "https://" . $_SERVER['HTTP_HOST'] . "/reset?token=" . $token;

If the server does not validate $_SERVER['HTTP_HOST'], an attacker who intercepts or crafts the password reset request can set:

Host: attacker.com

The application generates:

https://attacker.com/reset?token=abc123xy

…and sends that link to the victim’s email address. When the victim clicks it, the request — and the valid password reset token — goes to the attacker’s server.

This vulnerability is documented by OWASP under WSTG-INPV-01 and is a category within PortSwigger’s Web Security Academy under HTTP Host header attacks.

3. Impact of Host Header Injection

The impact varies significantly depending on where and how the application uses the Host header. These are the most consequential exploitation paths:

Password Reset Poisoning

The highest-impact and most commonly exploited consequence. If a password reset email is built using the Host header, an attacker can poison the reset link so the token is sent to a server they control. The victim receives a legitimate-looking email from the trusted domain, clicks the link, and the attacker captures the token — gaining the ability to reset the victim’s password and take over the account. No phishing page is required. The email came from the real application.

Web Cache Poisoning

Many caching systems — CDNs, reverse proxies, application-level caches — use the Host header as part of the cache key. If the application reflects the Host header value in the response (for example, in a canonical URL, a meta redirect, or a JavaScript variable), an attacker who can manipulate the Host header may be able to poison the cache. Subsequent legitimate users who request the same cached resource receive the attacker-influenced response — potentially containing a malicious URL or redirect.

Server-Side Request Forgery (SSRF)

In some architectures, particularly those using routing layers or microservices, the Host header is used to determine which internal service a request should be forwarded to. Injecting an internal hostname or IP address into the Host header can trick the routing layer into making requests to internal services that would otherwise be unreachable from the internet — a Host-header-based SSRF.

Open Redirect

Applications that build redirect URLs using the Host header can be exploited to redirect users to attacker-controlled domains. Even without a phishing page, redirecting a user from a trusted domain to an attacker site via a link that appears legitimate can be effective for credential theft.

Virtual Host Brute Forcing

In some cases, testing non-standard Host header values reveals hidden virtual hosts on the same server — internal admin panels, staging environments, or development servers that are not publicly linked but respond to requests on the same IP.

4. How to Prevent Host Header Injection

Prevention is not complicated, but it requires deliberate implementation decisions rather than trusting user-supplied input by default.

Validate the Host header against a strict whitelist. The application should maintain a list of every domain it legitimately serves — including all subdomains — and reject any request whose Host header does not match. This check should happen at the earliest possible point in request processing, before any application logic runs.

Never use the Host header to build URLs in server-side logic. Password reset links, email content, redirects, and canonical URLs should be constructed from a hard-coded, configuration-defined base URL — not from the request’s Host header. If the application is https://app.example.com, that value should come from a config file or environment variable, not from $_SERVER['HTTP_HOST'].

python

# Vulnerable
reset_url = f"https://{request.headers['Host']}/reset?token={token}"
# Safe
BASE_URL = os.environ.get("APP_BASE_URL") # e.g., "https://app.example.com"
reset_url = f"{BASE_URL}/reset?token={token}"

Reject ambiguous or overriding headers in your infrastructure. Proxy servers and load balancers should be configured to strip or override headers like X-Forwarded-Host before they reach the application layer, unless the infrastructure legitimately requires them.

Configure your web server to return a default error for unknown Host values. Nginx and Apache can be configured so that requests arriving with an unrecognised Host header return a non-informative response — preventing both information disclosure and host-based routing manipulation.

Get Unknown KP’s stories in your inbox

Join Medium for free to get updates from this writer.

Disable support for arbitrary Host headers in frameworks. Django’s ALLOWED_HOSTS setting, for example, exists precisely for this purpose — it causes the framework to raise a 400 error for any request whose Host header is not in the allowed list. Most modern frameworks have an equivalent mechanism.

5. Bypass Techniques for Host Header Injection

When a basic Host header manipulation is caught by server-side validation, attackers use a range of techniques to smuggle a controlled value past the defence. Understanding these is essential for building complete protection and for thorough testing.

X-Forwarded-Host

The X-Forwarded-Host header was designed to preserve the original Host when a proxy rewrites it. Many applications check the Host header for validation, but then use X-Forwarded-Host to build URLs — trusting it without the same validation.

Host: legitimate.com
X-Forwarded-Host: attacker.com

If the application uses X-Forwarded-Host when present, the attacker's value takes precedence in URL construction while the Host header passes validation.

Other Forwarding Headers

Similar logic applies to a range of non-standard forwarding headers that different frameworks and proxy configurations may prioritise:

X-Host: attacker.com
X-Forwarded-Server: attacker.com
X-HTTP-Host-Override: attacker.com
Forwarded: host=attacker.com

Testing each of these individually is part of a thorough assessment because different application stacks respond differently to each header.

Duplicate Host Headers

HTTP allows, in principle, multiple headers with the same name. When a server receives two Host headers, its behaviour is undefined and implementation-specific. Some servers use the first; some use the last; some concatenate them. This inconsistency can be exploited:

Host: legitimate.com
Host: attacker.com

Validation code checking $_SERVER['HTTP_HOST'] may get one value while URL construction code gets the other — depending on which PHP, nginx, or application layer component processes each.

Absolute URL in the Request Line

In HTTP/1.1, a request can include an absolute URL in the request line rather than a relative path. When this is done, some servers ignore the Host header entirely and use the domain from the absolute URL:

GET https://attacker.com/reset HTTP/1.1
Host: legitimate.com

Depending on the server’s request handling, the application may use the domain from the absolute URL for URL construction.

Adding a Port to the Host Header

Some validation implementations check the Host header value against a whitelist but do not account for port numbers. Adding an unexpected port can bypass a naive string comparison:

Host: legitimate.com:443@attacker.com
Host: legitimate.com:80 attacker.com

The aim is to confuse the validation logic into matching legitimate.com while the application's URL construction picks up a different portion of the string.

URL-Encoded and Whitespace Characters

Some WAFs and validation layers strip or normalise specific characters before comparison. Encoding characters in the Host value or injecting whitespace can cause the validation and the application processing to receive different effective values:

Host: legitimate.com%00attacker.com
Host: legitimate.com attacker.com

Indented Headers (Header Folding)

HTTP technically permits multi-line header values where continuation lines start with a space or tab. Though deprecated in HTTP/1.1 and not supported by most modern servers, older or custom implementations may still honour it, allowing value injection across lines.

6. Lab Walkthrough — Basic Password Reset Poisoning

Lab: Basic password reset poisoning
Platform: PortSwigger Web Security Academy
Objective: Exploit Host Header Injection in the password reset function to capture a valid reset token for the user carlos, then log into their account.

This lab is a direct demonstration of the password reset poisoning attack described in Section 3. The application uses the Host header to build password reset URLs without validating it — allowing an attacker to redirect reset tokens to a server they control.

Step 1 — Access the Lab and Locate the Password Reset Function

Open the lab in your browser. Navigate to the login page and click Forgot password. You will see a form asking for a username or email to send the reset link to.

Press enter or click to view image in full size

Step 2 — Open Burp Suite and Enable Intercept

Open Burp Suite and ensure the proxy is intercepting traffic. In your browser (configured to route through Burp’s proxy), enter carlos as the username in the forgot password form and click submit. Burp Suite intercepts the outgoing POST request before it reaches the server.

Press enter or click to view image in full size

Step 3 — Inspect the Intercepted Request

Look at the intercepted request in Burp’s Proxy tab. You will see the Host header is set to the lab’s domain. This is the value the application uses to build the password reset link it sends to the victim.

Press enter or click to view image in full size

Step 4 — Modify the Host Header to Your Exploit Server

PortSwigger labs provide a personal exploit server for each student. In Burp, change the Host header value from the lab’s domain to your exploit server’s domain. Then forward the request.

Host: YOUR-EXPLOIT-SERVER-ID.exploit-server.net
Press enter or click to view image in full size

Step 5 — Check the Exploit Server Access Logs

Navigate to your exploit server in the lab interface and open the access logs. The application sent a password reset email to carlos containing a link built with your modified Host header. When carlos (simulated by the lab) clicks that link, the request — including the reset token in the URL — hits your exploit server. Find the GET request in the logs and copy the token value from the URL.

Press enter or click to view image in full size

Step 6 — Use the Captured Token to Access the Password Reset Page

Take the captured token and craft the legitimate reset URL — this time using the real lab domain, not your exploit server:

https://YOUR-LAB-ID.web-security-academy.net/forgot-password?temp-forgot-password-token=CAPTURED_TOKEN

Navigate to this URL in your browser. The application presents the password reset form for the carlos account.

Press enter or click to view image in full size

Step 7 — Set a New Password for Carlos

Enter a new password of your choice and submit the form. The application accepts the valid token and updates carlos's password.

Press enter or click to view image in full size

Step 8 — Log In as Carlos and Complete the Lab

Navigate to the login page and log in as carlos using the new password you just set. The lab registers a successful login and displays the Lab Solved confirmation banner.

Press enter or click to view image in full size

What This Lab Demonstrates

The attack required no knowledge of carlos's real password. No phishing page was needed — the reset email came from the legitimate application. The only change was one header value in one HTTP request. The root cause is two lines of vulnerable server-side logic: using the request's Host header to build the reset URL instead of a hard-coded base URL. The fix is equally simple — one configuration change. The gap between that simplicity and the account takeover outcome is what makes this vulnerability worth understanding thoroughly.

Key Takeaways

  • The Host header is a client-supplied value that web applications frequently use in server-side logic — making it a trust boundary that many developers overlook.
  • Host Header Injection enables password reset poisoning, web cache poisoning, SSRF, and open redirect — all without modifying the application’s front-end or intercepting network traffic.
  • Prevention is straightforward: validate the Host header against a strict whitelist, and build all server-generated URLs from hard-coded configuration rather than request headers.
  • Bypasses like X-Forwarded-Host, duplicate headers, and absolute URLs mean that basic Host header validation is often insufficient — defence must account for the full range of headers an application or its proxy layer may process.
  • Professional penetration testing vendors will test Host header handling as part of any thorough web application assessment — including all known bypass techniques, not just the obvious direct header injection.

References

  1. OWASP Web Security Testing Guide — WSTG-INPV-01: https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/01-Testing_for_Reflected_Cross_Site_Scripting
  2. PortSwigger — HTTP Host Header Attacks: https://portswigger.net/web-security/host-header
  3. PortSwigger — Password Reset Poisoning: https://portswigger.net/web-security/host-header/exploiting/password-reset-poisoning
  4. RFC 7230 — HTTP/1.1: Message Syntax and Routing (Host header specification): https://datatracker.ietf.org/doc/html/rfc7230
  5. CWE-20: Improper Input Validation: https://cwe.mitre.org/data/definitions/20.html
  6. PortSwigger Research — Cracking the Lens: https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface
  7. OWASP Top 10 A07:2021 — Identification and Authentication Failures: https://owasp.org/Top10/A07_2021-Identification_and_Authentication_Failures/

--