HTTP Host Header Attacks
Understanding the HTTP Host Header
The HTTP Host header is a mandatory header in HTTP/1.1 requests that specifies the domain name of the server being requested. It allows multiple websites to be hosted on a single server (virtual hosting) by differentiating which site the client is trying to access.
For example, when you visit https://example.com, your browser sends a request with:
GET / HTTP/1.1
Host: example.com
...other headers...
Many web applications use the Host header for various purposes:
- Generating absolute URLs for redirects
- Password reset links and other security-sensitive functionality
- Server-side request validation
- Routing to the correct backend in load-balanced environments
Security Issue: Problems arise when applications implicitly trust the Host header, which is user-controllable and can be manipulated by attackers.
Types of Host Header Attacks
Attackers can exploit vulnerable applications through several Host header manipulation techniques:
Password Reset Poisoning
Many applications use the Host header to generate password reset links that are sent to users via email. If an attacker can manipulate the Host header, they can potentially generate password reset links that point to their malicious server.
For example, if a password reset function generates a link like:
https://{Host}/reset?token=abc123
An attacker could send a request with a modified Host header:
POST /forgot-password HTTP/1.1
Host: attacker.com
...other headers...
email=victim@example.com
The victim would receive an email with a reset link pointing to attacker.com, potentially revealing their reset token to the attacker.
Web Cache Poisoning
If a vulnerable application is behind a caching system, an attacker can use Host header manipulation to poison the cache with malicious content. When other users request the same resource, they receive the poisoned content from the cache.
Server-Side Request Forgery (SSRF)
Some applications use the Host header to make internal HTTP requests. By manipulating the Host header, attackers might be able to access internal services that are not intended to be publicly accessible.
Routing-Based SSRF
In load-balanced environments, the Host header might be used to route requests to different backend servers. Manipulating this header could allow attackers to reach internal systems.
Business Logic Exploitation
Applications might use the Host header in business logic decisions, such as determining which tenant's data to access in a multi-tenant application. Manipulating the Host header could potentially lead to unauthorized access to other tenants' data.
Host Header Manipulation Techniques
Attackers can manipulate the Host header in several ways:
Basic Host Override
Simply changing the Host header to a different value:
GET / HTTP/1.1
Host: evil.com
...other headers...
Duplicate Host Headers
Sending multiple Host headers in a single request:
GET / HTTP/1.1
Host: example.com
Host: evil.com
...other headers...
Different web servers handle duplicate headers differently. Some might use the first occurrence, others the last, and some might concatenate the values.
Host Header Injection via X-Forwarded-Host
Many applications behind proxies or load balancers trust the X-Forwarded-Host header over the Host header:
GET / HTTP/1.1
Host: example.com
X-Forwarded-Host: evil.com
...other headers...
Host Override via Absolute URLs
Using an absolute URL in the request line can sometimes override the Host header:
GET https://evil.com/ HTTP/1.1
Host: example.com
...other headers...
Line Wrapping/Folding
HTTP allows header values to be spread across multiple lines by starting continuation lines with a space or tab:
GET / HTTP/1.1
Host: example.com
evil.com
...other headers...
Warning: Different web servers, frameworks, and proxy servers handle Host header manipulation attempts differently. This inconsistency makes it important to test your specific environment for vulnerabilities.
Defense Strategies
To protect your applications from Host header attacks:
Avoid Using the Host Header for Security Decisions
The most effective defense is to avoid using the Host header for security-critical operations. Instead, hardcode the domain name in your application configuration.
Validate the Host Header
If you must use the Host header, validate it against a whitelist of allowed domains:
// Example validation in Node.js
const allowedHosts = ['example.com', 'www.example.com'];
const host = req.headers.host;
if (!allowedHosts.includes(host)) {
return res.status(403).send('Invalid Host header');
}
Use a Reverse Proxy
Configure a reverse proxy to set a trusted X-Forwarded-Host header and strip any user-supplied X-Forwarded-Host headers. Then use this trusted header in your application instead of the Host header.
Protect Password Reset Functionality
For password reset links and other sensitive URLs, hardcode the domain name rather than deriving it from the Host header:
// Instead of this:
const resetLink = `https://${req.headers.host}/reset?token=${token}`;
// Do this:
const resetLink = `https://example.com/reset?token=${token}`;
Implement Proper Access Controls
Ensure that internal services are not accessible based solely on the Host header. Implement proper authentication and authorization checks.
Use HTTP Strict Transport Security (HSTS)
Implement HSTS to prevent SSL stripping attacks that might be used in conjunction with Host header manipulation.
Regular Security Testing
Conduct regular security assessments, including penetration testing and code reviews, to identify and fix vulnerabilities related to Host header manipulation.
Best Practice: Remember that the Host header is user-controllable and should never be trusted for security-critical operations without proper validation.