What is HTTP Host Header
The Host header specifies the domain name of the server to which a client is making a request.
As a result of the growing trend of cloud based applications, it is quite common nowadays for web servers to host multiple websites on the same IP address. These websites could belong to the same owner or different owner depending upon the plan chosen. This type of hosting is called virtual hosting. This is were Host headers come to play, to help determine which target website/application is a particular request intended for.
It is also common for websites to be hosted behind a load balancer or a reverse proxy of some kind. This is very common in cases where a particular application is accessed via a CDN like Akamai or Cloudfare.
In such cases, the domain names of these applications resolve to a single IP of this intermediary host. These intermediaries in between use host headers to determine which target application to route the request to.
Hunting for host header vulnerabilities
If the host header is modified somehow, this could lead to routing the incoming request to an unknown destination. Host headers are used by backend application to build absolute urls. These host headers can be easily modified via proxy like burp. If the backend servers fail to validate these requests with host headers, attackers can inject malicious payloads into the host header, thereby manipulating the server side behavior.
Host Header validation
One way to check for these vulnerabilities, is by modifying the host header and seeing what kind of output the server returns. The output could either be an “Invalid Host Header”or server completing blocking the request without any error. Applications on the backend usually validate this by checking whether the Host header matches the SNI(Server Name Indication) from the TLS Handshake.
Injecting Duplicate Host headers
This can be achieved by intercepting a request and adding an additional Host header. This may just result in the request being blocked, but sometimes it may lead to some interesting behaviors, as the developer may not have anticipated such a scenario.
GET /directory HTTP/1.1
Host: example.com
Host: malicious-payload-here
This could be handled differently by different systems. The intermediary system or the CDN could give precedence to the first header, where as the backend could give precedence to the second header. In such a scenario, an attacker could supply the desired target in the first header and pass a malicious payload in the second header.
Supplying an absolute URL
The request line is usually expected to have the relative path on the target domain, but many servers are also configured to treat these request lines for absolute URLs.
GET <https://example.com/> HTTP/1.1
Host: malicious-payload-here
This could be exploited in the same way as exploiting a duplicate host header.
Using Host override headers
As discussed above, the architectures used nowadays consists of a CDN or an proxy in between the client and the target application. In such cases, the host header the target receives might contain the domain name of this intermediary system.
To solve this, the intermediary system usually injects an X-Forwarded-Host header, which will contain the original value of the Host header.
So whenever an X-Forwarded-Host header is present, the backend applications may refer to this instead. This behavior could be observed even when the intermediary system does not inject this header.
GET /directory HTTP/1.1
Host: example.com
X-Forwarded-Host: malicious-payload-here
Some other alternatives seen instead of X-Forwarded-Host are as follows:
- Forwarded
- X-Host
- X-HTTP-Host-Override
- X-Forwarded-Server
Real World Exploits
Password Reset Poisoning
An attacker manipulates a a vulnerable website into generating a password reset link pointing to a domain under their control. This can lead to attackers stealing the secret token required to reset passwords of a user account.
Bypassing Authentication with the Host Header
There will some pages on website which will only be accessible by a privileged user. However if this is setup incorrectly, an attacker can easily access a privileged page by changing the Host Header to something like “localhost”.
Web Cache Poisoning
This is a type of attack where in the attacker can tamper with a common cache that is used to serve content to multiple users. If a particular users response is cached to a shared web cache, which is very common in the case of proxy servers or CDNs, all users of the cache will continue to receive the same content. Host headers can be leveraged for such kind of attacks, in cases where the host header is included in the cache key.
To learn more about these attacks, I would definitely recommend checking out Portswigger. They also have dedicated labs simulating each of these attack vectors. Do try them out.
Preventing Host Header Attacks
The best way to prevent a Host Header attack is to avoid using the Host Header altogether in your web applications.
Disabling the host override headers like X-Forwarded-Host is also a good protection agains these attacks.
Many web application frameworks offer services, where in can use the hostname stored in the framework itself. This is typically asked by the frameworks during the setup itself, which is stored securely in a configuration file.
If there is an absolute requirement to use Host Headers and no way to avoid it, you build a whitelist of accepted host names. Because we all know, it is much secure to whitelist known hosts than to blacklist unknown ones.
Thank you for reading my blog. If you liked my blog, please do subscribe, I will be posting more interesting topics in the Application Security domain, which are widely used throughout the industry.