A question we have often seen in the past is to have a method to prevent IIS from sending the server identification header to a client which allows a client to identify which type of http server it is talking too. Usually this request comes from security concerns as knowing the server would allow a hacker to more easily be able to break into the system.
Although the above assumption from customers is very doubtable we still need to be able to provide a solution for this.
Out of the box all our IIS servers respond with a server header similar to the following (sample is for IIS 6.0):
Server: Microsoft-IIS/6.0
For IIS 5 and IIS 6 customers often used UrlScan which allows to remove the server header from the response.
On IIS 7 this tool cannot be installed – but due to the very modular structure of IIS 7 it is possible to remove or even replace the Server header in a much more convenient way: using a custom Module which is injected into the IIS 7 Pipeline. Such a module can be developed as well using managed or unmanaged code.
Here is a sample .Net module which replaces the server http header with a custom header:
using System.Text;
using System.Web;
namespace StefanG.ServerModules
{
public class CustomServerHeaderModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += OnPreSendRequestHeaders;
}
public void Dispose()
{ }
void OnPreSendRequestHeaders(object sender, EventArgs e)
{
// modify the “Server” Http Header
HttpContext.Current.Response.Headers.Set(“Server”, “Stefan’s Webserver”);
}
}
}
That’s it! When generating this module ensure to strong name it as it needs to be placed into the global assembly cache in order to allow IIS 7 to use it. To add the module to IIS 7 use the “Modules” configuration option on the server, choose “Add managed module” and select the module from the list of available modules.
Permalink
I think that this is a really good idea, and is a good idea to include as standard.
Permalink
Excellent. I’ve just migrated to IIS7/WS2008 and this will be one of the modules I use.
Permalink
Actually, you don’t need to put this module in the GAC to make it work. You can actually just copy + paste the code above into a file named "CustomServerHeaderModule.cs" and put it into a directory named "App_Code" off of your site root, or application root, register the module in your Web.config as follows:
<configuration>
<system.webServer>
<modules>
<add name="CustomServerHeader" type="StefanG.ServerModules.CustomServerHeaderModule" />
</modules>
</system.webServer>
</configuration>
or in the UI and it will work for that site / application immediately. (this approach is obviously not recommended for production deployments, but it is kind of fun and easy to test). For a more performant solution, compile the CustomServerHeaderMdoule.cs into a module.dll, and put it into the bin directory of your site/app. This method allows every site / app to modify the server header in their own custom way.
Of course, who would try to hide the fact they are running IIS7 anyway. 😉
Permalink
Hi Bill,
sure you are right. The method with the GAC allows a more centralized way to control this. A more flexible solution might be to read from the desired header to set from the web.config file of the web app.
And I also agree with your last sentence. 😉
Cheers,
Stefan
Permalink
This would have been trivially easy to add to the default build of IIS7. Microsoft deliberately chose not to do so. They don’t want people to change the Server header because of NetCraft and other Internet-wide inventories of web server versions. Microsoft wants IIS to be as widely identified as possible in these inventories for marketing purposes. Once again Microsoft sacrifices our security to their marketing plans. Thank you Microsoft for looking out for us…
Permalink
Hi Not Eric,
assuming that hiding the server header will give you any improvement in security is dangerous.
Someone really interested in hacking your system will not be hold off through this.
I personally think that hiding this name gives users a wrong feeling of security which might even cause more problems.
Cheers,
Stefan
Permalink
Hi Stefan:
Thank you for your reply.
Changing the Server response header does help to prevent showing up on scan lists which are targeting a particular make/model of web server. For example, a worm might be designed to only attack servers with a particular Server response header, or if a hacker is using Server headers to compile a list of servers of a particular type from a given IP range, then it would be better to not show up on that list.
It’s true that changing the Server header won’t fool a hacker for more than a second who is out to get your site in particular, but not all adversaries are out to get your site in particular, some are just scanning (using Server headers and other fingerprinting methods) to find any random site that meets certain criteria.
I agree it’s a minor issue, but in comparison with how absolutely trivial it would have been to add the ability to change the Server header when so many people ask about it (case in point, your post) it undermines Microsoft’s claims about really caring about our security when they don’t add it for the sake of a slight marketing benefit.
You might think I’m a Microsoft-basher, but I posted this for a reason: real Microsoft-bashers LATCH onto things like this, so why give them the opportunity?
Best Wishes, NE
Permalink
Anybody scanning servers looking for a particular type would be using one of the many security tools which identifies a server by the structure of it’s TCP response.
So in actual fact, removing the server header is useless in preventing people from identifying your server’s OS, etc.
However, it’s still something you definately want to be able to remove, so thanks for your solution for this.
Permalink
I support the removal of the Server HTTP response header by default, and Microsoft should have allow it to be disabled in the UI.
We know it’s not a fool-proof security measure, but I believe that one-extra hoop for a worm to jump through will make my box more secure than that of people with the Server response still intact.
My interest here however, is cutting down on bandwith as much as possible. I run high demand sites, the bandwith used to tranfer "Server: Microsoft-IIS/7.0" with EVERY request, for the millions of users served, the real cost to us by our ISP for transfering this is very high. (An extra gigabyte after 47million requests, gigabytes transfered cost money).
Permalink
When adding this module to web.config it is still possible to find the server software. Telnet to your HTTP server, and press Ctrl-C. The following response is sent (from IIS/7.5):
HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=us-ascii
Server: Microsoft-HTTPAPI/2.0
Date: Tue, 28 Jul 2009 14:47:07 GMT
Connection: close
Content-Length: 326
… HTML content saying: HTTP Error 400. The request verb is invalid.
Has anyone tried this after installing the module in GAC?
Permalink
Additionally I’ve added code to OnPreSendRequestHeaders:
HttpContext.Current.Response.Headers.Remove("X-AspNet-Version");
Without removing the X-AspNet-Version you’re identifying yourself as most likely running IIS version 5 or above, since ASP.NET doesn’t run on IIS 4. I’m unsure if mod_mono for Apache would add the X-AspNet-Version header.
Permalink
Hi Stefan:
Base on your solution , I’ve created a solution that can be run in local development (Cassini) without have it throwing a exception. Check it out: http://www.bugwriter.me/2010/01/removing-unnecessary-http-header-server.html
H.
Permalink
Remark on Corey’s post:
indeed responses created by IIS kernelmode component HTTPSYS cannot be customized.
Permalink
Hi,
Thanks for this article. One question:
I would like to remove one of the Set-Cookie headers that have been added to the response before it is sent back to the client. If I use repsonse.headers.remove("Set-Cookie"), then I guess all Set-Cookie lines will be removed. I cannot find a remove(index) method. Help appreciated!
Thanks,
Mats
Permalink
Hi Mats,
see here:
http://msdn.microsoft.com/en-us/library/ms178195.aspx
Cheers,
Stefan
Permalink
I know, but I want to eliminate the cookie from the response altogether as passing it to the client would mean a security issue.
Permalink
Hi Mats,
I don’t know if this is possible.
Cheers,
Stefan
Permalink
Thanks for the great post. One thing I noticed is that the latest URLScan (its current version is 3.1) is actually working on both IIS 7.0 and IIS 7.5. So we can simply add RemoveServerHeader=1 in URLScan.ini configuration file, if our goal is just to strip the server information from the header completely.
Thanks,
AMB
Permalink
If you're using IIS7 / Azure then have a look at this:
stackoverflow.com/…/removing-hiding-disabling-excessive-http-response-headers-in-azure-iis7-without
It shows the best way to disable these headers without using HttpModules.