Guide to HTTP host header injection

Every time you connect to a website you’re sending basic information across in the form of HTTP headers, these headers explain to the web server and other systems what page you’re looking for, what kind of action you’re looking to perform and where you’ve come from. There are a large number of headers but we’ll keep it simple for now, one of these headers is the Host header.

The host header tells the web server where the request should be sent. For example, the web server may host a number of different websites and so their systems may rely on the host header to know exactly which website your request is for.  The host header usually holds the domain of the website you’re visiting so the request can be forwarded on. I’ll include a sample web request below so you’re able to see what the web server is seeing.

GET /auth/forgot-password HTTP/2.0
Content-Length: 128
Referrer: /login
Connection: close

Although very simple, the example above does provide a basic understanding of what a web server sees when you click the forgot password link on a website. The first line is saying that you’ve made a GET request for the page /auth/forgot-password, the second line is the Host header. Depending on the functionality of the website this is where potential host header injection vulnerabilities can hide.

What is host header injection

Unless defined in a configuration file somewhere, many web applications do not know their domain, this means that should they need to restructure the website itself would continue to function. To get around this they can make us of built in commands and features such as PHP’s $_SERVER environment information. The $_SERVER is actually a list (or array if you’d like to get technical) containing information about the web server and your request, this information can range from the server name and file location to specific request header values.

For certain functionality some web applications access the the host header to build URL’s, one example would be when creating a password reset link. As the web application may not know its actual domain it may use PHP’s $_SERVER[‘HTTP_HOST’] when constructing the URL.

Although this URL can be broken down into a number of different parts, the pieces we’re interested in are the domain (website address) and the reset-token. If an attacker were able to get a hold of a reset token they’d be able to reset an account password and thus compromise a user account. So, how would an attacker get this? The link is sent to their email account after all.

When a website is building the reset URL it sometimes makes use of the Host header, an example of this can be seen at the link below.

$link = "http://".$_SERVER['HTTP_HOST']."/auth/reset-password?reset-token=".$random_token."&username=".$username;
send_email("Hello ".$username.", here's your password reset link - ".$link);

As you can see, the Host header is inserted directly into the password reset URL meaning that if an attacker were to alter this to a website they own then they’d be able to capture the reset token when the unsuspecting user clicked the link. With this token the attacker would then be able to go and use this to reset the account password. This type of host header injection attack is known as “Password reset poisoning”.

Protecting again host header injection

Never trust input which from the users computer. Although altering headers does take a little more know how, as this information is supplied by the attacker any application which has not taken specific measures to ensure this cannot happen could be at risk. Simply put, any information which is provided by the user should be checked and sanitized before being used.

Make use of a web application firewall (WAF). Common web application firewalls such as cloudflare can detect if the host header has been altered and prevent any requests from making it to the server.

Spread the love