ISAPI Filter to reject HTTP/1.0 requests

There is a known problem on IIS where the IP Address is leaked in the content-location header of the HTTP response. There is a fix for this and its documented here:

https://support.microsoft.com/kb/834141

The above KB also mentions that the issue might still occur even after using the above fix. It is discussed in detail in the “Mitigating Factors” section. Below is a snippet from the above article:

Mitigating Factors

After you set the UseHostName or SetHostName properties in IIS 6.0, it is still possible to see the server’s IP address in an HTTP response. By default, this does not occur. It results from how the response is generated and sent. For example, if you configure an HTTP redirect that results in an HTTP 302 response being sent, and your redirect code uses the server’s IP address, the IP address may appear in the Content-Location or Location header of the response. To work around this issue, do not use the server’s IP address in the redirect logic. Instead, use its host name or fully qualified machine name.

A similar type of behavior can occur if you configure custom error pages to perform a REDIRECT operation and you use IIS Manager to set the redirect target as a URL instead of a file. In this scenario, specify the file instead of the URL to keep the IP address hidden. The server's IP address can also be sent in an HTTP response if the following conditions are true:

  • The corresponding HTTP request did not include an HTTP:Host header value.
  • An ISAPI filter that makes a call to GetServerVariables(servername) during the SF_NOTIFY_PREPROC_HEADERS event is configured in IIS.

This is because PREPROC_HEADERS is called before IIS has read the configuration data; in this case, either UseHostName or SetHostName. Therefore, there is no other option but to return the IP address. If the request contains a Host value and the GetServerVariables(servername) call is made in PREPROC_HEADERS, SERVER_NAME will contain the value of the client's Host header. HTTP/1.1 Web browsers must include a Host header in their requests. Therefore, this scenario is much more likely to occur when the HTTP request is generated and sent by something other than a Web browser or when a Web browser uses HTTP/1.0.

 

So in real world the admins run a PCI scan on the server and it reports the server is vulnerable as it is leaking IP Address and suggests to follow the above support article.

However, even after applying the above fix, the issue is still seen as the scanners use a custom client which issue HTTP Requests over HTTP/1.0 protocol. The problem is here with the protocol and not with the product.

In the Mitigating factors section discussed above, it states 2 reasons why the issue is seen even after applying the fix. The first reason comes into picture for HTTP/1.0 protocol. There was a limitation in this protocol which assumed the client would send the hostname as a part of the HTTP Request, but never enforced it. This is the problem, since it assumes, if the incoming request doesn’t contain a hostname it would send back the response containing the IP Address of the server in the content-location header. This issue shouldn’t be seen in HTTP/1.1 as it mandates that the client should send the hostname as part of the HTTP Request.

Now, the questions is what is the fix?

ANSWER: Reject all HTTP/1.0 requests. This is the ideal solution as HTTP/1.0 protocol is obsolete and none of the current day browsers use this version.

Next questions is, how do we implement this on IIS?

ANSWER: Firstly, this issue is seen on all versions of IIS. As every server will support the protocol. So you will have to disable it. Going by the IIS versions,

For IIS 7.0 and higher:

Please refer the following blog on how to fix this issue on IIS 7.0 & higher:

https://www.asprangers.com/post/2012/02/09/IIS-7-IP-Address-revealed-on-redirection-requests-on-HTTP10-protocol.aspx

In the above article, they have used the URL Rewrite Module reject HTTP/1.0 requests.

For IIS 6:

There is no simple solution available on IIS 6. One way is to write a isapi filter which would reject all incoming requests. Below is a sample code to do the same.

  • Create a Empty C++ Project in Visual Studio 2005.
  • Add a .cpp file to the project and name it HttpVersionBlocker.cpp (or a name of your choice)
  • As we know, we need to define 2 important functions, GetFilterVersion and HttpFilterProc.
  • Below is the code snippet. Copy this to the above .cpp file
 #include <afxcoll.h>
 #include<stdio.h>
 #include<afxisapi.h>
 #include<afx.h>
 #include<stdlib.h>
  
 //-------------------------------------------------------
 // This function is the entry point to the ISAPI Filter 
 //-------------------------------------------------------
  
 BOOL WINAPI _stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
 {
         pVer->dwFlags = (SF_NOTIFY_PREPROC_HEADERS ); 
         pVer->dwFilterVersion = HTTP_FILTER_REVISION; 
         strcpy_s(pVer->lpszFilterDesc, "HTTP/1.0 Blocker"); 
         return TRUE; 
 }
  
 //-------------------------------------------------------
 // This function will be invoked on every request 
 //-------------------------------------------------------
  
 DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData) 
 { 
     char buffer[256];
     DWORD buffSize = sizeof(buffer);
     HTTP_FILTER_PREPROC_HEADERS *p;
  
     switch (NotificationType)  
     {
       case SF_NOTIFY_PREPROC_HEADERS :
       p = (HTTP_FILTER_PREPROC_HEADERS *)pvData;
       BOOL bHeader = p->GetHeader(pfc,"version",buffer,&buffSize); 
       CString Version(buffer);
  
       if(Version.Find("HTTP/1.0") != -1) 
       {
             // If HTTP/1.0 then Request, then change the URL
             p->SetHeader(pfc, "url", "/Rejected:HTTP/1.0_is_not_supported");
       }
       return SF_STATUS_REQ_HANDLED_NOTIFICATION; 
     }
     return SF_STATUS_REQ_NEXT_NOTIFICATION; 
 }
  • Go to Project properties and change the configuration type to Dynamic Library (.dll).
  • Add a new file and call it HttpversionBlocker.def. copy paste the below section into it:

LIBRARY "test"

EXPORTS

HttpFilterProc

GetFilterVersion

  • Build the project.
  • This will generate the HttpVersionBlocker.dll
  • Configure this as an Isapi filter in IIS. You can refer the below link to do this: Installing ISAPI Filters (IIS 6.0)

Alternatively, if one is not comfortable with coding there is another option. There is a 3rd party product that I’ve used in the past to achieve the same result. It is called WebKnight. Here is the link: https://www.aqtronix.com/?PageID=136.

This product is kind of a Application Firewall and can be used to block incoming requests on IIS.

The product can be downloaded freely, while they charge for the support.

You can try it at your own risk.

I don’t have much understanding of the product and neither do we support it so I’ll best leave it here.

NOTE: Neither of the solutions for IIS 6 is supported by Microsoft, as this is a problem with the protocol and not IIS.