Removing the IIS Server Request Header from ASP.NET Core Apps (any version)
If you're running an ASP.NET Core application on IIS, you have probably noticed that IIS injects a Server header into your HTTP headers that advertises the server platform, which is not always welcome.
Here's what that header looks like:
/HttpHeaderswithIis.png)
Now you might think it's easy: Slap on a Response.Headers.Remove("Server") and you're done, right? But no, that doesn't work with the IIS Server header because... well, it's different than other headers.
If you're running ASP.NET Core with Kestrel you also get a Server header, but it's a little different with Kestrel in that it generates its own Http header as part of the ASP.NET framework processing, while the IIS setting is generated by IIS's internal pipeline processing.
Why is the Server Header different?
Adding and removing headers in ASP.NET Core is kind of a hornet's nest, because there's no direct built-in way to do it globally for all requests in ASP.NET Core. I talked about how to do this using some custom middleware in a previous post, and one of the options of the middleware I discussed was the ability to remove headers from an outgoing HttpRepsonse request.
That's all fine and good for framework generated headers which you can add and remove programmatically on a per request basis or via generic middleware.
But the IIS Server header is different: It's not actually generated as part of the ASP.NET Core framework processing, but rather by IIS's internal pipeline and is injected by IIS very late in the Response processing.
Removing the IIS Server Header - in web.config
For this reason the reliable and most effective way to remove the Server header is to do it as part of the IIS processing configuration, in this case by using web.config and setting one of the requestFiltering options:
<system.webServer>
<security>
<requestFiltering removeServerHeader="true" />
</security>
</system.webServer>
This feature only works in IIS 10 which was introduced with Windows 10 and Windows Server 2016.
This works great and it requires no other changes in your application. You'll just have to ensure that you publish your custom web.config that includes the above <security> section with your application.
Remember, if you publish an ASP.NET Core project it either uses the
web.configthat you provide as part of your project in the root folder or it creates one for you when you publish.It's best to provide a
web.configin your project:
Note that
web.configis overwritten on any publish operation regardless of whether you provide one in your project or not, so be sure not to change the copy in the deployed application folder as it gets overwritten.
Overwrite the Server Header
Another option if you're willing to leave a server header in there but use misdirection - like show a version of Apache or nginx or BleatingSheepServer instead of IIS - you can overwrite the server header with a new value.
So for example using the middleware I described in the previous post you can do:
app.UseCustomHeaders((opt) =>
{
// ...
opt.HeadersToAdd.Add("Server", "nginx");
});
This produces:
/FakeServerHeader.png)
Apparently IIS won't inject its own Server header, if your application already has set it. This means you can use your own header and add some misdirection for potential attacks against your server.
Enjoy all the Linux and WordPress attack links in your IIS logs after this... 😄
Note that if you're running this code on Kestrel, you still get the default
Kestrelserver header rather thannginx- the above fake header trick doesn't work. For Kestrel the only way to affect theServerheader is to remove during startup builder configuration (see below).
What doesn't work
I don't want to belabor the point, but since this issue has gone through a number of changes since earlier versions of ASP.NET Core, I want to take a moment and discuss some other approaches that don't work and why.
Removing header via code in Middleware
Although you can useResponse.Headersor the generic middleware to add and remove headers, theServerheader can't be removed this way because it's added by IIS itself very late in the IIS request processing pipeline. Therefore you can't remove it from ASP.NET code as far as I know.Kestrel Hosting Configuration Options
Several older Posts and StackOverflow posts point at using Kestrel configuration options to remove theServerheader via theBuilderconfiguration. While that works for Kestrel's Server header, it has no effect on when hosted in IIS.var builder = WebApplication.CreateBuilder(args); builder.WebHost .UseKestrel(option => option.AddServerHeader = false); .UseIIS();This does not work for the IIS header! It only works for the Kestrel header.
Using the web.config
<customHeaders>Section
Like the other approaches mentioned above you can't use the IIS<customHeaders>configuration section to<remove value="server">either.
Summary
The moral of the story is: This is an IIS setting and you should use IIS to override it, so use the web.config setting or overwrite the header with your own bogus value for misdirection.
Resources
Other Posts you might also like
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Getting the Client IP Address in ASP.NET Core
- Getting the ASP.NET Core Server Hosting Urls at Startup and in Requests
- Resolving Paths To Server Relative Paths in .NET Code
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
The Voices of Reason
# re: Removing the IIS Server Request Header from ASP.NET Core Apps (any version)
@James - thanks for the reminder - I've added a note into the post.
# re: Removing the IIS Server Request Header from ASP.NET Core Apps (any version)
In the post you have '''opt.HeadersToRemove.Add("X-Powered-By");'''
but the screenshot shows the X-Powered-By header. Assuming that's a mistake?
# re: Removing the IIS Server Request Header from ASP.NET Core Apps (any version)
@James - good catch, I didn't notice. I took a look and it appears that recent versions of ASP.NET have changed when the headers are injected by the ASP.NET Core framework. It appears the headers are now injected after all the processing is completed. I took a look and set it breakpoint inside of the 1) the MVC request handler, and 2) inside of the middleware and neither one of them shows the ASP.NET generated headers in Response.Headers - only those that the application is adding. Can't remove headers that aren't already present.
So the remove functionality is somewhat broken in the middleware handler - that may no longer be possible to do.
I've removed the remove operations from the sample.
/webConfigInProject.png)
# re: Removing the IIS Server Request Header from ASP.NET Core Apps (any version)
The web.config removal works as long as the app is running on IIS 10+.