I’ve encountered some issues with spoofing of the Host value in HTTP transactions. In order to close security holes related to these types of attacks, I need to securely detect what the domain of the running ASP.NET site. Unfortunately, all of the references I find suggest you use Request.ServerVariables["HTTP_HOST"]
or Request.Url.Host
. By submitting invalid HTTP packets, I have been able to set invalid host values and observer the behavior they're causing with both function calls. The behavior I'm seeing is different depending on the type of .NET environment I use.
In IIS 6, the injected value always shows up, no matter if I access the request directly in an MVC Controller action, or in a location that requires me to access the values through HttpContext.Current.Request
.
In the Visual Studio 2012 ASP.Net Development Server, I only see the injected values in library code we deployed to the project through a NuGet package. In the NuGet package I have to use the HttpContext.Current
since the code runs outside of the scope of the web application. When I stay within the scope of the web application's namespace, even if I have to call the HttpContext.Current
, it will provide the correct unspoofed value.
For all of this testing, I have been using ASP.NET 4.0. Has this behavior changed in ASP.NET 4.5 and IIS 8? Is there a way to securely get the domain name? It is also possible to do the same attack against PHP, but Apache has a way that can prevent these types of attacks. Does IIS?
Example of the code I've been having problems with:
string siteName1 = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
string siteName2 = HttpContext.Current.Request.Url.Host;
Example of an invalid HTTP Packet:
GET: https://sampledomain.com/Items/Index
Host: fakedomain
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: max-age=0
I've done my testing with the Firefox extension Live HTTP headers which has allowed me to quickly record and replay my requests to the web server.