What are HTTP host header attacks?

HTTP Host header attacks have become a common technique for attackers and have several variants. Before we dive deeper into the attacks and what they enable, let’s start by covering what an HTTP host header is.

What is the HTTP Host header?

The HTTP Host header provides host and port information and is intended to help origin servers determine which resources to use when they service requests for multiple domains. 

Other Host headers

Sometimes applications supplement the Host header with additional Host-like headers such as “X-Forwarded-Host”, “X-Host”, and other variations. We’ll use these in some of the attack descriptions below, as they are vulnerable in the same way as the Host header if used improperly.

The types of HTTP Host header attacks

The Host header is a critical part of using the internet but applications open themselves to vulnerabilities when the Host header is implicitly trusted, used for additional functionality, or misconfigured. Attackers can exploit this behavior by injecting different types of content into the Host header, which can lead to more severe vulnerabilities, including:

  1. Host Header Poisoning

  2. Web Cache Poisoning

  3. Password Reset Poisoning

  4. Server Side Request Forgery 

Depending on how an application is using the values provided by the Host header, it could also enable other attacks such as Cross-Site Scripting or SQL injection, just as any other user-provided input could when it isn’t processed safely. For now, let’s assume that you’re not using the Host header in raw SQL queries and cover the more direct attacks.

1. Host Header Poisoning

In the most simple of cases, an application may use the Host header value for redirecting traffic, such as to the application’s login page. If the application uses the Host header to build the redirection link, an attacker can send the following HTTP request:

GET / HTTP/1.1
Host: www.attackers-domain.example.com

And generate a response redirecting to their controlled domain:

HTTP/1.1 302 Found
...
Location: http://www.attackers-domain.example.com/login.php

By itself, this attack isn’t very useful since it’s difficult to get a targeted user to make this request. However, Host Header Poisoning can be combined with other attacks to increase its efficacy. 

2. Web Cache Poisoning

Web Cache Poisoning isn’t a Host header vulnerability per se, but a delivery mechanism that makes the aforementioned Host Header Poisoning exploitable. Let’s say an application doesn’t use the Host header to build its redirection links (good!) but instead uses an alternative header such as X-Host to build them (bad!). In this scenario, an attacker can then inject their domain in X-Host to poison the redirect; however, they still need a way to deliver that redirect to users.

This is where web cache poisoning kicks in. Web caches typically use portions of an HTTP request as “keys” to know when to use cached content rather than sending the request to the origin. This key typically includes the Host header and may include any other headers. In our example, if X-Host is not part of the cache key but is unsafely used in the response (like in our redirect example), attackers can use the cache to deliver other users their malicious redirect. The attacker then finds a way to get their request cached to serve it to other users.

Let’s take a look at an example of web cache poisoning. First the attacker gets the following request cached that includes their malicious domain in the X-Host header, which will be used in a redirect:

GET / HTTP/1.1
Host: www.super-cool-fun-domain.example.com

X-Host: www.attackers-domain.example.com

A benign user then decides to visit the application, sending a normal request:

GET / HTTP/1.1
Host: www.super-cool-fun-domain.example.com
X-Host: www.super-cool-fun-domain.example.com

Assuming the attacker’s request was cached based on the path and Host header, the benign user now receives the poisoned cached response, redirecting them to the attacker’s page:

HTTP/1.1 302 Found
...
Location: http://www.attackers-domain.example.com/login.php

Web cache poisoning attacks rely on the mismatch between headers that are used as a cache key and headers that are used by the application to formulate responses. In the above example, the X-Host header provided a way to poison cached responses, redirecting users to a malicious site instead of the actual application.

3. Password Reset Poisoning

Password Reset Poisoning is very similar to our previous Host Header Poisoning in that the vulnerable application uses the Host header to construct the password reset link they send to  the requested user during the reset workflow. For example, say an attacker sends the following POST request to request a password reset for the “alice” user:

POST /password-reset HTTP/1.1
Host: www.attackers-domain.example.com
...


user=alice

The application uses the value from the Host header to construct the reset link and sends an email to the alice user with the link:

www.attackers-domain.example.com?reset_token=super-random-reset-token-value-12345

If the user clicks the link, the attacker captures the reset token and can reset the user’s password to their own value.

4. Server-Side Request Forgery

Server-Side Request Forgery (SSRF) is a vulnerability that allows an attacker to cause the server-side application to make requests to an arbitrary location. In a Host Header SSRF, the attacker is exploiting the routing used by systems sitting between the user and the server-side application. If this middleware (e.g., a load balancer) is vulnerable to Host Header SSRF, the attacker can possibly use this to interact with internal-facing systems they otherwise would not have access to. A common way to test for this is to put a unique, controlled domain (e.g., Portswigger’s Burp Collaborator, or ProjectDiscovery’s interactsh) in the Host header value. If that unique domain receives a DNS lookup or other request from a system in the targeted applications network path (e.g., the load balancer) during a Host header Attack, then it may be vulnerable to SSRF. These attacks tend to be complex in practice but also devastating, as demonstrated thoroughly in James Kettle’s research.

Real world examples of HTTP Host header attacks

Now that you have an understanding of the types of Host header attacks, let’s take a look at some real-world examples.

CVE-2022-29933: Password Reset Poisoning in Craft CMS

SEC Consult found that Craft CMS’ default installation constructs password reset emails using the value of the “X-Forwarded-Host” HTTP header. In this example, an attacker injects their controlled domain in the X-Forwarded-Host to poison the password reset link for the alice user as follows:

POST /index.php?p=admin/actions/users/send-password-reset-email HTTP/1.1
Host: <installation-domain>
X-Forwarded-Host: www.attackers-domain.example.com
...
Cookie: CRAFT_CSRF_TOKEN=[...]


loginName=alice@example.com

When the alice@example.com user receives their password reset email, it contains a link to the attacker’s controlled domain:

http://www.attackers-domain.example.com/index.php?p=admin/set-password&code=<reset-code>&id=<uuid>

If the user follows the link, the attacker has now captured their reset code and can reset their password to take over the account.

Blind SSRF in Slack via X-Forwarded-Host Injection

This attack bypasses weak X-Forwarded-Host validation to achieve blind SSRF on files.slack.com. First, files.slack.com attempts to validate the Host header and the X-Forwarded-Host header during processing, returning an HTTP 500 response code when they’re not files.slack.com. However, the X-Forwarded-Host validation can be bypassed by appending a @ character at the end of the domain. So, the attacker sets up a callback domain to capture requests (e.g. with Burp Collaborator, ProjectDiscovery’s interactsh) and sends the following request to slack.files.com:

GET /<URI> HTTP/1.1
Host: files.slack.com
...
X-Forwarded-Host: files.slack.com@www.unique-attackers-domain.example.com

The files.slack.com in the URL constructed from the X-Forwarded-Host header is treated as the HTTP user (HTTP BasicAuth), and the www.unique-attackers-domain.example.com is treated as the hostname. The attacker receives a request from a backend system, confirming the successfulSSRF. From here, several different blind SSRF techniques can be used to attempt to leak information, interact with backend systems, and more.

How to prevent HTTP Host header attacks

There are several ways to prevent HTTP Host header attacks that vary in their effectiveness and drawbacks. Below you will find actionable solutions to prevent this type of attack.

Avoid using the Host header value and its variants in application code

The easiest way to prevent Host header attacks is by avoiding the use of the Host header value in your application code. Additionally, using server-side configurations or relative URLs instead will completely thwart Host header attacks.

Perform strict validation on Host header values

If you have to use the Host header value, the following techniques should be used to prevent Host header attacks:

  1. Validate the Host header is in an allowed list of values. For example, if your application only uses three domains, ensure the Host header is only one of those three values.

  2. Validate there is only one Host header. Duplicate Host headers can sometimes be used to bypass the validation if the validation and usage of the header end up pulling different values from the request.

  3. Avoid using Host header alternatives and overrides such as X-Host or X-Forwarded-Host, and if you have to, follow the same recommendations provided for the Host header.

How Fastly helps prevent HTTP Host header attacks

Follow Fastly’s guide on preventing cache poisoning to ensure additional protections are in place.

If you’re using Fastly’s Next Gen Web Application Firewall, you can add in additional protections to guard against HTTP Host header Attacks to block all requests with invalid Host headers (e.g., ones not in your allowed list of domains).

Summary

The Host header is a vital part of the internet (and Fastly), but when the Host header is implicitly trusted, used for additional functionality, or misconfigured, attackers can exploit this behavior by injecting different types of malicious content into it. This can enable multiple types of attacks, including host header poisoning, web cache poisoning, password reset poisoning, and server-side request forgery (SSRF). Using solutions we’ve outlined, combined with Fastly’s guidance to prevent cache poisoning, applications can prevent host header attack variants.