To understand the host header injection, we must first look at what a host header is, how it works, and how to manipulate it to inject malicious content, poison web caches, reset passwords, and more.
Here’s what you need to know about the host header and this injection attack.
What is an HTTP Host header?
The HTTP host header is a request header that specifies the domain that a client (browser) wants to access. This header is necessary because it is pretty standard for servers to host websites and applications at the same IP address. However, they don’t automatically know where to direct the request.
When the server receives a request, it checks the host header parameter to determine which domain needs to process the request and then dispatches it. Sometimes the header may be amended in being routed to the appropriate domain. That is where the host header injection may occur.
The reason many websites are hosted on one IP address is due to, on one hand, the exhaustion of IPv4 addresses, as well as due to the popularity of cloud hosting.
There are two main ways multiple websites are accessible under the same IP address. First, these are the cases when there is a virtual host or an intermediary system.
When multiple websites or applications are hosted on one server, this is known as virtual hosting. The server has a single IP address in this scenario, and received requests are routed to the relevant domains.
Alternatively, multiple websites can be found on one IP address when intermediary systems are used. In this case, a website may be located on a separate server but is accessed via an intermediary such as a reverse proxy server, a content delivery network (CDN), web syndication, or some other form of traffic routing.
For similar reasons as above, this requires indication for the intermediary about where to direct incoming requests.
What is the function of the HTTP Host header?
Given that websites and applications don’t have their own personal IP addresses, the purpose of the host header is to provide the server with information about the proper recipient of the request located downstream.
The host header specifies which domain (back-end) hosted with the server should receive and process the client’s request, and the server forwards it accordingly. The back-end then responds to the request following the same route since it doesn’t know how the request entered the network.
HTTP Host header example
For example, if you wanted to view our main blog page, the request would include the following host header:
GET /security-penetration-testing-blog HTTP/1.1 Host: www.crashtest-security.com
So what happens if the host header in the request is flawed? Unfortunately, most servers are configured to serve the first virtual host (i.e., a default website) to requests that don’t have a recognizable host header.
Since the host header is user-controlled, sending requests with arbitrary host headers to the first virtual host on any server is possible. It is possible because there is no way to check whether the domain included in the host header corresponds to the IP address part of the initial Transmission Control Protocol (TCP) handshake. So in effect, anyone who can manipulate the incoming request can tamper with the host header.
This opens the door for host header injections that manipulate server-side behavior and serve malicious content to users.
What are Host header injections?
A host header injection exploits the vulnerability of some websites to accept host headers indiscriminately without validating or altogether escaping them.
This is dangerous because many applications rely on the host header to generate links, import scripts, determine the proper redirect address, generate password reset links, etc. So when an application retrieves the host header, it may end up serving malicious content in the response injected there.
An example would be a request to retrieve your e-banking web page: https://www.your-ebanking.com/login.php.
If the attacker can tamper with the host header in the request, changing it to https://www.attacker.com/login.php, this fake website could be served to users and trick them into entering their login credentials.
The above is a rough example of how a host header could be injected. A successful host header injection could result in web cache poisoning, password reset poisoning, access to internal hosts, cross-site scripting (XSS), bypassing authentication, virtual host brute-forcing, and more!
Following are the two main HTTP host header injection scenarios.
Web cache poisoning
Web cache poisoning occurs when an attacker can manipulate a caching proxy server or other intermediary systems served by a website.
For this purpose, the attacker must first poison the proxy itself. Once they have achieved this, they can capture unexpecting users looking for a specific website and provide them with a fake one.
Depending on the specific case, this is done by changing the host header, using multiple host headers, or using the X-Forwarded-Host header. The latter is used when an application rejects host headers that are tampered with. In essence, these are just different approaches toward the end goal of serving poisoned content.
If users are fooled successfully, they may end up running scripts that open the door for other attacks.
Password reset poisoning
Another impact that a host header injection can have is to poison the password reset functionality. As a result, they can trick users into clicking a reset link and then resetting and capturing their new password. For understanding this problem, it’s necessary to understand the difference between relative and absolute URLs.
Relative and absolute URLs
For the most part, websites and applications do not need to know the domain they operate under and provide relative URLs instead of absolute ones. Relative URLs are a better choice from a development perspective and offer greater security.
However, an absolute URL is required in certain instances, such as when links are generated in response to a password reset request. In addition, an absolute URL is necessary because users will be coming to the website from the outside, so they need to know the complete domain address.
If a web application uses the host header when generating the reset link, this creates the possibility for it to serve a poisoned link to users if the host header has been tampered with. If users do not pay attention to the link and the website looks similar to what they are expecting, they can effectively deliver their credentials to attackers.
Host header injection vulnerabilities
Host header vulnerabilities may arise for several reasons. First, even if the host header is handled carefully, there are ways to override the host and perform an injection. Many vulnerabilities are due to default configuration options on the server-side or when third-party components are integrated without being properly secured.
Common reasons for this type of injection attack include:
- Servers accepting arbitrary or malformed host headers due to a default or fallback option
- Flawed domain validation that allows attackers to tamper with the port or insert a random subdomain
- Ambiguous requests that contain duplicate host headers, absolute URLs in the request line, along with a host header, indented headers, etc.
- Smuggled HTTP requests
- Injected override headers such as X-Host, X-Forwarded-Server, and others
How to prevent Host header attacks?
Depending on your configuration type, there are different ways you can prevent host header injections. Of course, the most straightforward approach is to distrust the host header at all times and not use it in server-side code. This simple change can essentially eliminate the possibility of a host header attack being launched against you.
However, this may not always be possible, and if you need to use the host header, you should consider implementing the following measures.
Use relative URLs as much as possible.
Start by considering whether your absolute URLs are vital. Frequently, it is possible to use relative URLs instead.
If you need to use specific absolute URLs, such as transactional emails, the domain must be specified in the server-side configuration file and taken from there. This eliminates the possibility of password reset poisoning, as it will not refer to the host header when generating a token.
Validate Host headers
User input must always be considered unsafe and should be validated and sanitized first. One way to validate host headers, where needed, is to create a whitelist of permitted domains and check host headers in incoming requests against this list. Respectively, any hosts that are not recognized should be rejected or redirected.
To understand how to implement such a whitelist, see the relevant framework documentation.
When validating host headers, you must also establish whether the request came from the original target host or not.
Whitelist trusted domains
Already at the development stage, you should whitelist all trusted domain names from which your reverse proxy, load balancer, or other intermediary systems are allowed to forward requests. This will help you prevent routing-based attacks such as a Server-Side Request Forgery (SSRF).
Implement domain mapping
Map every origin server to which the proxy should serve requests, i.e., mapping hostnames to websites.
Reject override headers
Host override headers, such as X-Host and X-Forwarded-Host, are frequently used in header injections. Servers sometimes support these by default, so it’s essential to double-check that this is not the case.
Avoid using internal-only websites under a virtual host
Host headers injections can be used to access internal (private) domains. Avoid this scenario, do not host public and private websites on the same virtual host.
Create a dummy virtual host
If you use Apache or Nginx, you can create a dummy virtual host to capture requests from unrecognized host headers (i.e., forged requests) and prevent cache poisoning.
Fix your server configuration
Host header injections are frequently due to default settings, and faulty or old server configurations. Inspecting and fixing your server configuration can eliminate significant vulnerabilities that open the door for injections.
What is a Host header injection?
The HTTP host header injection is an attack in which a malevolent actor tampers with the host header in a client request. This misleads the virtual host or intermediary system to serve poisoned content to the client in the response.
Are Host header attacks dangerous?
Host header injections can potentially be dangerous as they may lead to a poisoned web cache or poisoned password reset functionality. Luckily, they are easily prevented with the proper server configuration.
How to avoid Host header attacks?
Most importantly – do not trust host headers at all or without proper prior validation. If you have no other choice but to use host headers, implement a whitelist of allowed domains.
What are the risks associated with a Host header injection?
A successful host header attack can lead to many different issues such as a poisoned web cache or poisoned password reset, cross-site scripting or server-side forgery requests, SQL injections, session hijacking, and more.