In the last post about bypassing web filters, I discussed how SNI spoofing works and how this can also be prevented by web filters. This post is about another bypass technique called Host Header spoofing.
What Is a Host Header
The Host
header is an HTTP request header sent by the client (usually a browser) to the webserver as part of the HTTP request, and specifies the hostname of the server1. Because a webserver can host multiple websites on the same IP address, this information is required to deliver the correct website. This is called virtual hosting. Reverse proxies can also use this header to determine to which backend system the incoming requests should be sent.
In the following example, Alice connects to the webserver with the IP address 203.0.113.5
, which hosts the websites a.example.net
, b.example.net
, and c.example.net
. As Alice’s browser sends the Host
header b.example.net
, the webserver knows to deliver the files for the right directory.

Nowadays, HTTP traffic is almost always wrapped in TLS, and since the Host
header is part of the HTTP request, it is also encrypted. This is illustrated below.
First, the browser establishes a TLS session with the server. In the TLS handshake, the hostname is sent in the SNI ①. Then, an HTTP request is sent to the server ② inside the TLS tunnel ③. As part of this request, the browser again specifies the hostname in the HTTP Host
header ④:

Note: Normally, you would not be able to inspect the decrypted messages exchanged in a TLS tunnel. Instead of the HTTP GET request, you would simply see encrypted data. For this setup, the TLS keys were dumped using the SSLKEYLOGFILE
variable2,3 and imported into Wireshark, which allows on-the-fly decryption of TLS traffic.
Host Header Based Filters
Companies often intercept and inspect TLS traffic on proxies. For this to work, the Certificate Authority (CA) certificate of the proxy must be installed on all client devices. This is therefore only possible in corporate environments, where the company manages all clients, so they can install the proxy CA. Without the installed proxy CA, users would receive a TLS certificate error and be able to detect that someone is looking at their traffic (this is also known as a Man-in-the-Middle attack).
With a setup as described above, the proxy is able to decrypt and inspect all traffic, and use the information from the HTTP request (like the Host
header) to determine whether a request is legit or not. This approach is used to block dangerous files (such as .exe
files), known malicious websites, specific website categories like gaming, or file uploads exceeding a certain size to prevent data exfiltration.
In most cases, such filters work with a blocklist (or known-bad) approach. However, in rare cases, we have seen customers implement the opposite, by defining a list of allowed (or known-good) websites, that can be accessed through the filter.
Bypassing Simple Web Filters Using Host Header Spoofing
When proxies only rely on the Host
header to determine if a request is legitimate, this can be exploited to bypass such web filters.
This requires control over the HTTP request, which can be achieved by malware running on the system or by an attacker or user with system access attempting to bypass the web filter.
Imagine you have the following situation where Alice is able to access the website legit.example.net
but the access to evil.example.com
is blocked by the firewall based on the Host
header evil.example.com
:

Alice (or a malware on her computer) is now able to bypass the web filter by connecting to evil.example.net
(leaving the SNI evil.example.net unmodified), but specifying the Host
header legit.example.net
:

Host
headerThe final IP, TLS and HTTP packet structure looks like this:

Since we only changed the Host
header, but not the SNI, there is also the added benefit that we can bypass web filters that perform SNI matching with the hostname/SAN from the certificate (see previous blogpost about SNI spoofing).
Example Using curl
To craft such a request is easy. Using curl
, we can control the Host
header as shown below:
curl -H "Host: legit.example.net" https://evil.example.com
Here we can see that the SNI is unchanged ① to match the certificate subject but the HTTP request ② contains the spoofed Host
header ③:

Host
headerNote: For demonstration purposes, the TLS connection is decrypted again to allow inspection of the contained HTTP traffic.
We found such bypasses in projects, where the customer e.g. blocked large file uploads to most websites to prevent data exfiltration. In this case, this imposed restriction on our C2 communication, because the C2 implant was not able to transmit larger chunks of data back to our server. By overriding the Host
header to a value which was excluded from the blocklist (the customer’s own file sharing solution), the filter could be bypassed, allowing unrestricted communication from our C2 implant.
Host Header Spoofing Protection and Limitations
The bypass technique discussed above only works if the proxy only uses the Host header to decide whether a website should be blocked or not, ignoring other mechanisms such as SNI inspection/matching.
However, in most cases web filters will perform additional checks to improve resilience against such bypasses. For example, a proxy could verify that the hostname in the SNI and in the Host
header are identical, and drop requests where they are different.
Example: Fortinet FortiGate
The Fortinet FortiGate firewall/proxy has such a feature called “Domain Fronting Protection”4 which blocks mismatches of the hostnames:

The HTTP response looks like this if this is detected:
HTTP/1.1 403 Forbidden
[...]
[...]
<h3>403 domain fronting blocked</h3>
<p>The webserver reported that an error occurred while trying to access the website. Please return to the previous page.</p>
[...]
The message in the log looks like this:
type="utm" subtype="webfilter" eventtype="domain-fronting" srcip=172.17.0.2 dstip=198.51.100.23 dstport=443 hostname="legit.example.net" msg="Domain fronting detected" rawdata="HTTP Host <legit.example.net> does not match SNI <evil.example.com>"
This protection feature is enabled by default but can be disabled:

More about domain fronting will be explained in the next post.
Takeaway
Host header spoofing is a rather simple bypass technique, and – given a correctly configured web filter solution – is easily preventable. Nonetheless, it’s always worth looking for it in your next penetration test or in your own infrastructure!
Also keep in mind that it’s not always about being able/not able to access a specific site, but also about bypassing other restrictions such as large file uploads, or downloading certain file types.
References
- RFC 2616, HTTP/1.1, “The Resource Identified by a Request”: https://www.rfc-editor.org/rfc/rfc2616#section-5.2 ↩︎
- Everything Curl,
SSLKEYLOGFILE
: https://everything.curl.dev/usingcurl/tls/sslkeylogfile.html ↩︎ - Internet Draft, The
SSLKEYLOGFILE
Format for TLS, https://www.ietf.org/archive/id/draft-ietf-tls-keylogfile-03.txt ↩︎ - Fortinet Documentation, Fortigate, Domain Fronting Protection: https://docs.fortinet.com/document/fortigate/7.6.2/administration-guide/639769 ↩︎