How reliable is the "host" in an incoming HTTPS request?
Solution 1:
The Host
header is part of the HTTP request that specifies which virtual host on the web server the request is made to.
It has nothing to do with the source of the request. Anyone can make a HTTP / HTTPS request to your web server, and specify google.com
in the Host
header. Then it is up to your web server to decide what it wants to do with the request.
Browsers typically add HTTP Referer
header to requests, which indicates what is the source page that provided the URL for this request. However, Referer
field is also untrusted user input, and it can be easily faked.
An example:
User is visitiing http://www.example.com/example
website, which has a hyperlink to http://www.example.org
. User clicks on the link. User's browser sends the request to IP address of www.example.org
, with the following HTTP headers:
Host: www.example.org
Referer: http://www.example.com/example
Recently browsers have started to strip Referer
header contents so that it contains only the root URL: http://www.example.com
, when making cross-domain requests.
Overall, you cannot trust any HTTP request header to contain exactly the data you expect, since it is untrusted user input.
Solution 2:
The Host: request header (RFC 7230 § 5.4) is untrusted user input. It is supplied by the user agent to indicate the (virtual) host that the HTTP request pertains to. Any malicious user agent can connect to your server and make a request with an invalid Host: header.
You are meant to validate that the content of the Host: header corresponds to your actual hostname before processing the request. Normally the web server (nginx, Apache, etc.) takes care of this for you and then passes the request to your app. But if you expose the app directly to the Internet, not behind a regular web server, then you must validate it yourself.