What Is Host Header Injection?
Host header injection is a web application vulnerability that occurs when a server uses the HTTP `Host` header from a request to perform sensitive operations — constructing URLs for redirects, generating password reset links, building absolute URLs in responses — without validating that the header contains the expected value.
The HTTP `Host` header is included in every HTTP/1.1 request and specifies the domain name the client is connecting to. Under normal circumstances it contains the legitimate hostname of the server. But an attacker can send a request with an arbitrary value in this header, and if the server trusts it uncritically, that arbitrary value propagates into the application's behaviour.
Why Applications Trust the Host Header
The `Host` header exists because a single web server can host multiple websites on the same IP address (virtual hosting). The server uses the `Host` header to route the request to the correct application. Many frameworks and applications then use the same header to construct absolute URLs for:
- Password reset email links: `https://{host}/reset?token=abc123` - OAuth redirect URIs - `Location` headers in redirects - Canonical URL meta tags - CORS origin validation - Cache keys (see the relationship with cache poisoning)
When any of these operations uses the raw `Host` header value without validation against a whitelist of legitimate domains, the application is vulnerable.
Attack Vectors
Password Reset Poisoning
This is the most commonly exploited Host header injection vector in real-world attacks. The flow:
1. Attacker initiates a password reset for a victim's account (they know the victim's email address) 2. In the reset request, the attacker modifies the `Host` header to `attacker.com` 3. The application generates a password reset token and constructs the reset link: `https://attacker.com/reset?token=SecretToken123` 4. This poisoned link is emailed to the victim 5. The victim clicks the link, their browser sends the request to `attacker.com` (the attacker's server) 6. The attacker receives the reset token in their server logs 7. The attacker uses the token to reset the victim's password and take over their account
``` Malicious password reset request:
POST /forgot-password HTTP/1.1 Host: attacker.com Content-Type: application/x-www-form-urlencoded
email=victim@company.com
Response from server: Email sent to victim@company.com with link: https://attacker.com/reset?token=a1b2c3d4e5 ```
The victim's email client shows a reset email apparently from the legitimate application. They click the link. The attacker steals the token.
Web Cache Poisoning via Host Header
When the `Host` header is excluded from the cache key but reflected in the response, it becomes a vector for cache poisoning (closely related to the dedicated cache poisoning vulnerability class). An attacker sends:
``` GET / HTTP/1.1 Host: attacker.com ```
If the response includes `<script src="https://attacker.com/app.js">` and this response is cached by a CDN or proxy under the normal URL key, all subsequent users receive the poisoned response serving JavaScript from the attacker's domain.
Server-Side Request Forgery (SSRF) via Host Header
Some reverse proxy configurations use the `Host` header to determine the upstream server to forward the request to. An attacker who can control the `Host` header might redirect the request to an internal service:
``` GET / HTTP/1.1 Host: internal-admin.company.local ```
If the reverse proxy routes based on the `Host` value and doesn't validate against a whitelist, this request may reach an internal service not intended to be externally accessible.
Open Redirect via Host Header
Applications that construct redirect URLs from the `Host` header can be used for phishing:
``` GET /login?redirect=/dashboard HTTP/1.1 Host: attacker.com
Response: Location: https://attacker.com/dashboard ```
The victim follows what appears to be a legitimate redirect from the application but lands on the attacker's site.
OAuth State Parameter Poisoning
OAuth flows that construct the `redirect_uri` dynamically using the `Host` header can be manipulated to redirect OAuth authorization codes to attacker-controlled servers. This results in account takeover on any application using the poisoned OAuth flow.
Bypassing Host Header Validation
Some applications attempt to validate the `Host` header but do so insufficiently. Common bypass techniques:
**Duplicate Host headers** — some servers process the first `Host` header while others process the last; sending two headers exploits this inconsistency:
``` GET / HTTP/1.1 Host: legitimate.com Host: attacker.com ```
**Absolute-form request with conflicting Host** — HTTP/1.1 allows an absolute URL in the request line. If the server uses the request line URL but the application uses the `Host` header:
``` GET https://legitimate.com/ HTTP/1.1 Host: attacker.com ```
**Port-appended Host header** — bypasses simple string comparison validation:
``` Host: legitimate.com:attacker.com ```
**X-Forwarded-Host header** — many applications trust `X-Forwarded-Host` as an override to the `Host` header, set by proxies and load balancers. If this header is accepted from untrusted clients, it's effectively the same vulnerability with a different header name.
Other related headers that applications may trust: - `X-Host` - `X-Forwarded-Server` - `X-HTTP-Host-Override` - `Forwarded`
Real CVE Examples
**CVE-2020-7791 — Drupal password reset poisoning** — Drupal's password reset mechanism used the `Host` header to construct reset URLs without adequate validation, enabling password reset poisoning.
**CVE-2018-14773 — Symfony HttpFoundation Host header injection** — Symfony's `Request::getHost()` method didn't properly validate the `Host` header, allowing injection of arbitrary values. Applications built on Symfony that used `getHost()` for URL construction were vulnerable.
**CVE-2016-4483 — WordPress password reset poisoning** — WordPress core used the `Host` header in password reset emails. An attacker could poison the reset link to point to an attacker-controlled domain, stealing the reset token when the victim clicked.
These vulnerabilities appear across frameworks, CMS platforms, and custom applications precisely because the pattern — "use the Host header to construct URLs" — seems natural and is widely replicated.
Prevention
**Whitelist permitted Host values on the server** — configure your web server or application framework to reject requests with `Host` headers that don't match your expected domain(s). In Nginx:
```nginx server { listen 80; server_name legitimate.com www.legitimate.com;
if ($host !~* ^(legitimate\.com|www\.legitimate\.com)$) { return 444; } } ```
**Never use the Host header to construct password reset or authentication URLs** — hard-code the application's domain in your configuration and use that value for URL construction. The `Host` header should not be the source of truth for your own domain:
```python # WRONG reset_url = f"https://{request.headers['Host']}/reset?token={token}"
# RIGHT SITE_URL = "https://legitimate.com" # from config, not from request reset_url = f"{SITE_URL}/reset?token={token}" ```
**Strip or validate `X-Forwarded-Host` at your perimeter** — if your load balancer or CDN sets this header, ensure it's stripped from client-originating requests before they reach your application. Only your own infrastructure should be trusted to set forwarding headers.
**Use framework-level host validation** — most modern frameworks have mechanisms to configure trusted hosts. Django's `ALLOWED_HOSTS`, Rails' `config.hosts`, Laravel's trusted proxy configuration — use them.
Yrzo AI's continuous scanning tests for Host header injection across password reset flows, redirect mechanisms, and URL construction patterns in all web-accessible endpoints.
**[Test your application for Host header injection → Start free at yrzoai.dev](https://yrzoai.dev)**
A password reset email pointing to an attacker's server. The victim clicks it. The account is gone. Validate your Host header — it's a one-line fix with significant impact.
Find out if your website has these vulnerabilities
Yrzo AI runs 44 automated security checks and delivers a full report in under 20 minutes. Starting from £399.
Scan your website →