•  Oxford: +44 (0)1865 877830 
  • Manchester: +44 (0)161 713 0176 
  •  London: +44 (0)203 5983740 
  •  New York: +1 646-781-7580 
  • Dubai: +971 (0)4 427 0429

Easily Remove Unwanted HTTP Headers in IIS 7.0 to 8.5

You are here

07

Apr

Easily Remove Unwanted HTTP Headers in IIS 7.0 to 8.5

The StripHeaders module is a Native-Code module for IIS 7.0 and above, designed to easily remove unnecessary response headers and prevent information leakage of software and version information, which can be useful to an attacker.

  • See the installation section for information regarding deploying StripHeaders within your organisation.
  • See the configuration section for information regarding removing additional headers.

Binary - Download from GitHub

Source - https://github.com/Dionach/StripHeaders/

Why create a module to remove headers?

Web servers, frameworks and applications often set response headers that reveal software in use and version information. Such headers are optional and whilst they serve no real purpose, can often assist an attacker in identifying vulnerabilities in a system.

As an example, the following headers are contained in responses from recently installed IIS 8.5 web server:

HTTP/1.1 200 OK [...] Server: Microsoft-IIS/8.5 X-Powered-By: ASP.NET X-Powered-By: ARR/2.5

Headers beginning "X-" are non-standard headers and are completely optional. The "Server" header is defined in RFC 2616, which actively encourages server implementors to make setting this header a configurable option due to the benefit it can provide to an attacker. Unfortunately, most implementors have ignored this encouragement. Whilst many web servers support removing specific version information from the "Server" header, or overwriting it with a new value, few allow it to be easily removed entirely.

Removing Unnecessary Headers in IIS

IIS 7.0 and above does not contain an option to configure whether or not the "Server" header is sent in responses. Historically, there have been a number of workarounds available for removing the "Server" header, unfortunately none of these methods are ideal and as of IIS 8.0 are no longer supported. There are a number of resources available that discuss the available methods in length, however the main methods are:

  1. Overwrite the "Server" header using the IIS Manager HTTP Response Headers or URL Rewrite modules. Both of these modules can be used to set the server header to a custom or blank value, however will not remove it entirely.
  2. Use UrlScan (http://www.iis.net/downloads/microsoft/urlscan). This requires additional configuration and is only supported up to IIS 7.0.
  3. Create a custom IIS ASP.NET managed module and remove the "Server" header using the "PreSendRequestHeaders" event. This only works for requests that pass through the ASP.NET pipeline, as such the "Server" header will still be sent for static content. Whilst IIS can be configured to force all requests through the pipeline, this is less than desirable. Additionally, use of the "PreSendRequestHeaders" event is no longer recommended by Microsoft (http://www.asp.net/aspnet/overview/web-development-best-practices/what-n...).

In addition to the "Server" response header, it is common to see other unnecessary headers in an IIS environment, such as "X-Powered-By", "X-Aspnet-Version" and other custom version headers for applications such as Outlook Web Access and SharePoint. These headers are configured in various locations and as such removing these headers becomes a significant task, particularly across a large infrastructure. This can involve making IIS server configuration changes, web application configuration changes and even registry changes.

The solution to removing unnecessary headers in IIS responses lies in the use of a Native-Code module. Native-Code modules differ from the more common managed modules in that they use the WIN32 APIs rather than the .NET framework. This means that a Native-Code module can process all requests, not just those that pass through the ASP.NET pipeline. Additionally, due to the low overhead, Native-Code is also arguably faster, although this would normally only be a consideration for web servers that process a very large number of requests.

The IIS StripHeaders Native-Code Module

About

The StripHeaders Native-Code module has been created to allow an easy to deploy method of removing unnecessary headers in IIS 7.0 and above. By default, it removes the "Server", "X-Aspnet-Version" and any "X-Powered-By" headers and additional headers to remove can be easily configured.

In an effort to make the module as easy to use as possible, it is provided as an MSI installer, which can be installed directly on web servers, or deployed through group policy to all required servers in an organisation.

The main component of the StripHeaders module is stripheaders.dll, being the actual IIS module. Using this file alone would still require a fair amount of configuration and as such the installer automatically takes care of this work. The installer performs the following tasks:

  1. Installs stripheaders.dll
  2. Registers the Native-Code module with IIS using the appcmd.exe command
  3. Extends the IIS configuration schema to allow setting of headers to remove
  4. Adds default settings to the IIS configuration to remove the common "Server", "X-Powered-By" and "X-Aspnet-Version" response headers
  5. Adds a registry setting to remove the "Server: Microsoft-HTTPAPI/2.0" response header.

The "Server: Microsoft-HTTPAPI/2.0" response header is added by the "http" service, this is normally only sent in responses if the request fails to be passed to IIS, for instance when no application pools are available. The registry setting only takes effect when the service is restarted. The installer makes no attempt to restart the service (in fact the installer takes a number of steps to ensure that it never needs to restart any services, as this is not desirable on production systems). This setting will therefore take effect when the server is restarted for scheduled maintenance, such as when Windows Updates are installed. If you wish it to take effect immediately, you can manually restart the "http" service. This will also stop the IIS service. Please note that, other services, such as the Web Management Service (WMSVC), also depend on the "http" service and will need to be manually started.

net stop http iisreset /force 
Installation

Download and run the latest installer on your IIS servers.

Alternatively, use Group Policy to assign the installer package to all IIS servers within an organisation. See http://support.microsoft.com/kb/816102 for more information.

Configuration

The StripHeaders module uses a very simple syntax to add additional headers to remove. The configuration is contained in the applicationHost.config file and can be edited directly or from the Configuration Manager module in the site settings in IIS Manager. The default configuration is shown below:

[...]
<configuration> [...]
  <system.webServer> [...]
    <stripHeaders>
      <header name="Server" />
      <header name="X-Powered-By" />
      <header name="X-Aspnet-Version" />
    </stripHeaders>
  </system.webServer>
</configuration>
[...]
Further Reading

If you would like to know how the module works, full source code for the StripHeaders module and installer is available from https://github.com/dionach/stripheaders.

If you would like to learn more about how Native-Code modules work and how to create them, more information is available in the Native-Code development overview in the MSDN (http://msdn.microsoft.com/en-us/library/aa347657(v=vs.90).aspx).

Posted by Phill

48 Comments - Easily Remove Unwanted HTTP Headers in IIS 7.0 to 8.5

Ben (not verified) May 13, 2014

Reply
The native module does not appear to be able to remove X-Powered-By , this is added as a custom header by default in the apphost config. It should be added by the IIS protocolsupportModule (native) ... The order of the execution and the event used in your code should mean the header is visible by the time your code runs. But this does not appear to be the case. I tried this on a couple of W2K8R2 / IIS7+ servers. One way around this would be to modify the wix installer to remove the default X-powered-by header as an additional edit to the apphost config.

Ben (not verified) May 13, 2014

Reply
Hi, Looked at this some more, I think there are two issues here (have now tested this out with success) 1. You should be registering for the same event as the ProtocolSupportModule (which IIS uses to manage custom headers) and 2. The order of the modules in IIS is very important and this custom module needs to run _after_ the ProtocolSupportModule. Failed request tracing (on a status of 200) can be used to verify this. Having made these two changes to a copy of your source the issues are fixed and the module now works as intended on a base W2K8R2 IIS7+ box with a standard ASP NET Web site and WCF service (net4 integrated).

Phill May 15, 2014

Reply
Hi Ben, thank you for the very detailed bug report. I hope you are finding the module useful. I've made the changes you have suggested, so the module now uses the OnSendRequest event and the execution priority puts it after ProtocolSupportModule. The changes and updated installer are now on GitHub and this post. The installer will upgrade any previous versions you have installed as well. Thanks again for the feedback.

Andrew Woolterton (not verified) June 30, 2014

Reply
Hi, just wondering if there is a 32bit version of the app , or a work around, since we run 32 bit isapi filters. the module is pretty cool!

Phill June 30, 2014

Reply
Hi, the code is not 64bit specific, so it should be possible to compile it for 32bit without any problems. However, I have not done any testing for 32bit application pools. I will do some testing and get back to you asap.

Andrew Woolterton (not verified) July 01, 2014

Reply
Many thanks!, some of our app pools require to be in 32 but mode when we access the app the pools die due to bitness. Not sure if the dll can be compiled to run in any mode?

Andrew Woolterton (not verified) July 02, 2014

Reply
I tried compiling as win32 but it didn't work too well on Windows 2008, maybe there is something I have missed :( Did you have any luck creating a x86 version. I did not see an option to compile a x86 only win32 which seems slightly different. Kind Regards Andrew

Phill July 03, 2014

Reply
Apologies for the delay, took me slightly longer than exception to fix this. Unfortunately you cant create an Any CPU native code module, instead a 64bit version needs to go into Windows\System32 and a 32bit version needs to go into Windows\SysWOW64. I have added iis_stripheaders_module_1.0.2.msi to GitHub and this post. Let me know if you have any problems.

Igor Kudrin (not verified) July 07, 2014

Reply
Windows Server 2012 R2. Everything works after manually registering with this command C:\Windows\System32\inetsrv\appcmd.exe install module /name:StripHeadersModule /image:%windir%\system32\inetsrv\stripheaders.dll /add:true /lock:true

Phill July 07, 2014

Reply
Hi, that's quite strange as that is the same command the installer runs to install the module, and a default 2012 R2 install was the test platform. If you bump into this let me know and I will look into it further.

Tom (not verified) August 25, 2014

Reply
I had this same issue on a fairly new Windows 2012 Server, After manual registration it seems to work fine. Great idea to put al this server header issues into 1 setup ! Regards, Tom

Tom (not verified) August 27, 2014

Reply
After having this issue on a numer of server, I have now found a possible cause of the problem and a workaround. I think this issue has to do with UAC. When i just doubleklick the installer, the Module is not registeren in iis, but when i start the installer from a elevated command prompt it works fine. Probably you have to force elevation in the installer to solve the problem.

Phill August 28, 2014

Reply
Thanks for the information, that makes a lot of sense. I am using WiX Toolset for the installer which is supposed to default to requiring elevated privileges, however the installer may not be launching the command to register the IIS module with admin rights, as this is an external call to appcmd.exe. I will take a look and do some testing and release an updated installer.

Forest (not verified) July 07, 2014

Reply
Works for me out of the box hiding the headers. I used the GUI to register the .dll. I'm confused, however, on where exactly you edit the config file. I can't find the find to directly edit it nor can I find a way to do this in IIS? Any ideas?

Phill July 10, 2014

Reply
Hi, the easiest way to edit the config is to use the "Configuration Editor" module in IIS Manger. The settings for StripHeaders are in the "system.webServer" section. The other option is to edit the "applicationHost.config"file directly, which is in XML format is and located in the IIS directory (Windows\System32\inetserv).

Manish U (not verified) September 05, 2014

Reply
Nice post. Before I try this out. I have a question here. I would appreciate if you could help me out. My trading partner does not wants these headers in addition to X-Powered ones (below). Can all of these be also removed by this module? Content-Length, Content-Type, Date.

Phill September 05, 2014

Reply
Hi, the module will remove the Content-Type header, but not the Content-Length and Date headers, as these are inserted by IIS at the very end of the pipeline in order to ensure that they are correct. I would strongly advise against removing any of these headers as they are part of the HTTP specification and will likely cause problems with client applications, such as web browsers, when processing the response. There is no security benefit to removing these headers so I would query exactly why your trading partner wants these removed.

Bert (not verified) September 09, 2014

Reply
Tried this on Windows 2012 R2 and it appears to install and extend the schema as advertised. However the "Server" header is not removed. Any ideas?

Phill September 10, 2014

Reply
Hi, it is a bit hard to tell without more information, but I would start by double checking that the module has correctly registered with IIS - it should be displayed in the Modules option of IIS Manager. It can be re-added using the following command: %windir%\system32\inetsrv\appcmd.exe install module /name:StripHeadersModule /image:%windir%\system32\inetsrv\stripheaders.dll /add:true /lock:true"

Albert Churba (not verified) September 13, 2014

Reply
I checked modules before any action and it was listed. I have executed the outlined appcmd and received the a successful output. Command output: GLOBAL MODULE object "StripHeadersModule" added MODULE object "StripHeadersModule" added After re-adding the module, the module is working as advertised. Thanks for the support.

Shane Argo (not verified) October 03, 2014

Reply
Hello Phil. Aside from being a useful product, this module is by far the greatest reference out there when it comes to developing a native IIS module. I am the author of the (currently managed) open source HSTS IIS Module: http://hstsiis.codeplex.com/. For the next version, I will be redeveloping this as a native module. The documentation available regarding the development of native IIS modules leaves a lot to be desired. Due to this, I have been using the source code for the StripHeaders module as a reference. Combine this with the fact that my module has fairly similar functionality (albeit, yours removes headers and mine adds them in) I am concerned that I will be seen as plagiarising our code. I fully intend to reference and credit your code within mine and within the documentation, but I want to ensure that you are happy with this. I understand that the module is open source, but it seems strange to develop my module as a fork of yours just because the boiler plate is the same. I could modify superficial things such as the variable names, but I feel this is worse than just leaving them the same and giving you the credit you deserve. What do you think would be the most ideal way for me to credit you for your work. Regards, Shane.

Phill October 03, 2014

Reply
Hi Shane, I understand the difficulty in finding references for native modules, I was in the same position when I first started writing this one. I am completely happy for you to copy as much of the code you need to. To be honest, the percentage of the code that is specific to checking the IIS config and removing the headers is very small. The code is truly open source, as in you are more than welcome to do what you like with it, if that is making another version of your module which is also of great benefit to people then even better. As for credit, a link back from your project would be nice, but it is ultimately up to you. If you run into any problems with your native module, send me a message as it may be something I came across as well. Thanks, Phill

Shane Argo (not verified) October 16, 2014

Reply
Hi again Phill. Thank you again for the fantastic reference. I have just released v2.0.0.0 of the HSTS IIS Module which ended up being based heavily on yours. I managed to get the configuration to work at the web site level, instead of the server level. If you are interested, all the of the source is available on GitHub: https://github.com/AllTheDucks/hsts-iis-module. My module also includes and extension to the IIS Manager GUI. Again, thank you! Cheers, Shane.

Phill October 17, 2014

Reply
Hi Shane, you are welcome, I am glad the code is useful as well as the module. And now there are two references for anyone wanting to make a native module :). I will have to take a peek at your IIS Manager extension - this is something I wanted to add originally but never got round to. Phill

Phill October 17, 2014

Reply
One point to note, in order to support 32bit app pools with a native code module you need to: (1) Put a 64bit dll in Windows\System32\inetsrv\ (2) Put a 32bit dll in Windows\SysWOW64\inetsrv\ (3) Register the module in IIS as normal using "%windir%\system32\inetsrv\module.dll" as the location. This way Windows will handle loading the correct version depending on the app pool bitness. Phill

MetUys (not verified) October 13, 2014

Reply
Hi Phill (and Shane if you are monitoring this), I am looking to do both: strip unnecessary header content AND add the HTST header in as well. Would you guys not think about compiling one native solution for both these since they are similar in nature? Early awaiting your response. PS: have you ever run these in conjunction with IIS ARR setups? Kind Regards

Phill October 17, 2014

Reply
Hi, personally, I think they are better suited to remaining as individual modules as, although they are both heading with headers, it is for different purposes. StripHeaders works fine with Application Request Routing, in fact my initial testing was on a ARR server. StripHeaders will remove headers set by both the ARR server and the destination servers.

John (not verified) November 07, 2014

Reply
I built from the source (1.0.2) and tried to install on a new 64-bit 2012 R2 machine. I installed IIS roles etc. and then when I ran the strip headers msi it failed. It complained about not being able to modify applicationHost.config in the windows\SysWow64\Inetsrv\Config directory. I looked there and the file did not exist. Knowing that Syswow64 is for 32 bit apps I copied the .config files from 64 bit system32\Inetsrv\Config folder and then was able to run the install successfully.

Hopeful (not verified) November 13, 2014

Reply
Would you expect to see a dramatic increase in CPU usage when using StripHeaders?

Phill November 13, 2014

Reply
No, StripHeaders has to do very little processing so there shouldn't be a noticeable difference in CPU usage.

Hopeful (not verified) November 14, 2014

Reply
Thanks for the prompt reply. I asked because in load tests we perform without StripHeaders installed, CPU utilization ranges from 8-10 percent vs. 40-50 percent when StripHeaders is installed. Might you suggest a method and/or tool to get a little more insight into the CPU utilization? Like you, we also presumed there would be very little processing involved, so we are trying to track down the source of the increased CPU utilization. Any insight or tips you might have would be greatly appreciated. Thanks again for the tool and for your time!

Phill November 14, 2014

Reply
I have just done some testing and I am seeing a similar issue with CPU increase when attempting a lot of requests (200/sec). Naturally I would expect a small difference but not what we are seeing, if you bear with me, I will do some further testing and look for any optimisations I can make.

Hopeful (not verified) November 16, 2014

Reply
I appreciate your looking at this and any insight you might have. Cheers.

Hopeful (not verified) November 20, 2014

Reply
Phill - hope all is well. Just wanted to touch base to see if there's any update or if you have any questions. Thanks again!

Phill November 21, 2014

Reply
Hi, sorry for the delay, I haven't had a great deal of time to look at this this week. As StripHeaders is a request level module (it has to be to remove headers) the only place I can see the delay and CPU increase is in the MS APIs for accessing the IIS configuration. Unfortunately these are pretty poorly documented but I need to do some testing in order to pin down exactly where the issue is. I will have a look into this over the weekend.

Hopeful (not verified) November 29, 2014

Reply
Any luck getting to the root cause? Thank you!

Phill December 01, 2014

Reply
Hi, it seems the CPU increase is due to the overhead of using the IIS configuration API to access the settings for the headers to remove on a per request basis. Unfortunately the module has to be a per request module in order to remove headers and as such there is no way to reuse the same instance of the configuration class over multiple requests. Having experimented, the overhead of hard coding headers to remove is not noticeable in my tests - however it is impractical to have no way to configure the headers to remove. I have tested reading headers to remove from a text file, and this seems very fast, with only a small (one or two percent) increase in CPU usage. Let me clean up my code, and I will create an updated release.

Phill December 02, 2014

Reply
After some trial and error with the poorly documented MS API I have been able to only load the configuration when the module is first loaded. This fixes the performance issues for me, but I would be grateful if you could try it out and report back. Version 1.0.3 is on the GitHub releases and also available from this page.

Hopeful (not verified) December 13, 2014

Reply
I am happy to report that our testing of your version 1.0.3 yields much better performance results which is consistent with your experience. We greatly appreciate your support throughout and solving our issue!

Sean (not verified) March 23, 2015

Reply
2012R2 installed msi .. no stripping occurs.. I believe I am missing something in the limited documentation.

Sean (not verified) March 24, 2015

Reply
1) Run installer 2) Register: C:\Windows\System32\inetsrv\appcmd.exe install module /name:StripHeadersModule /image:%windir%\system32\inetsrv\stripheaders.dll /add:true /lock:true 3) go into IIS Mgr, root server, open HTTP Module section, view ordered list 4) if StripHeaders is not listed, click Configure Native Modules on the right side window, checkbox select "StripHeaders" then ok 5) move StripHeaders to right after ProtocolSupportModule Worked for 2012 R2, IIS 8.5 and ARR 2.5

David Robinson (not verified) March 26, 2015

Reply
Hi there, I found this component and it does a great job removing the headers from all content from my server side MVC site, however the site also contains quite a lot of static content which however still has the headers. Is static content in such a way supported? Thanks in advance

David Robinson (not verified) March 26, 2015

Reply
Hi, I've installed this in IIS 8.5 and it works fine for server side code but it does not work for static content which is served directly from IIS. Any ideas as to whether this should work? Thanks in advance

Azhar (not verified) April 15, 2015

Reply
Hi. After installing the StripHeaders module on 2012 R2, we've found that when IIS Worker Processes (w3wp.exe) shuts down when the after the idle time-out period configured on the application pool, we see that the process terminates unexpectedly, instead of terminating gracefully: "A process serving application pool 'applicationpoolname' terminated unexpectedly. The process id was '5168'. The process exit code was '0xc0000096'." We also see the following two errors output to the application event log each time it terminates unexpectedly: "Faulting application name: w3wp.exe, version: 8.5.9600.16384, time stamp: 0x5215df96 Faulting module name: nativerd.dll, version: 8.5.9600.17415, time stamp: 0x545040de Exception code: 0xc0000096 Fault offset: 0x000000000002aa20 Faulting process id: 0x5b0 Faulting application start time: 0x01d07780b6bb7312 Faulting application path: c:\windows\system32\inetsrv\w3wp.exe Faulting module path: c:\windows\system32\inetsrv\nativerd.dll Report Id: 18f5f144-e374-11e4-80cd-005056933a5a Faulting package full name: Faulting package-relative application ID:" and: "Windows cannot access the file for one of the following reasons: there is a problem with the network connection, the disk that the file is stored on, or the storage drivers installed on this computer; or the disk is missing. Windows closed the program IIS Worker Process because of this error." This doesn't occur when the module is not installed, and has occurred across multiple web servers we have installed the module on (which are all 2012 R2). Is this something that has been reported to yourselves previously, or has anyone else experienced this behaviour? Thanks, Azhar.

Bob Hope (not verified) April 29, 2015

Reply
Hi, after installing this module, I get the above error whenever the w3wp process either recycles or is shutdown (be it a time out when not in use or a stop of the application pool) I've had a look into it as much as I could, but I cannot figure out why it's happening. It looks as if the module is unloaded as the process attempts to run it's exit code and therefore is no longer available to be terminated. This is on a fully patched windows 7 x64 machine.

GSmith (not verified) April 30, 2015

Reply
I installed the MSI package on my server and performed these 2 commands net stop http iisreset (iisreset /force wasn't a valid command) but then when I browsed the response header I still see the server header with IIS 8.5 What else am I missing?

G.Smith (not verified) April 30, 2015

Reply
Hello, I tried this line and it seemed to have fixed it: C:\Windows\System32\inetsrv\appcmd.exe install module /name:StripHeadersModule /image:%windir%\system32\inetsrv\stripheaders.dll /add:true /lock:true

Danny (not verified) December 30, 2015

Reply
Kudos! Worked great on an AWS Windows Server 2012 R2 (version 6.2 Build 9200) IIS8 (Version 8.5.9600.16384) I downloaded then ran it.

Leave a comment