Cloud Zone is brought to you in partnership with:

Paul Bouwer is an Integration Consultant and co-organiser of the Brisbane Azure User Group. Paul’s experience in the IT industry spans 15 years and numerous technologies. He has worked in the following industries: Internet Service Provider, Airline, Travel, Telecommunication, Health, SaaS (Software as a Service) and Gaming. He is excited about Azure as a cloud platform and its feature set. Paul tweets at @pbouwer and blogs at blog.paulbouwer.com. Paul is a DZone MVB and is not an employee of DZone and has posted 2 posts at DZone. You can read more from them at their website. View Full User Profile

ASafaWeb, Excessive Headers and Windows Azure

01.12.2013
| 2008 views |
  • submit to reddit

 Troy Hunt is a Microsoft MVP for Developer Security and regularly blogs and tweets about security principles.  He is the creator of ASafaWeb, the Automated Security Analyser for ASP.NET Websites. Troy has observed that around 67% of ASP.NET websites have serious configuration related security vulnerabilities. ASafaWeb makes scanning for these vulnerabilities dead easy and provides both remediation and additional reading around the resolution.

Troy blogged about excessive response headers in Shhh… don’t let your response headers talk too loudly.

By default, an ASP.NET application running on IIS returns a lot of information about the server and framework via the headers. This information can be used to help exploit vulnerabilities that are present in the technologies the headers identify. If any of the following response headers are returned, ASafaWeb will report a warning for this scan:

  • Server
  • X-Powered-By
  • X-AspNet-Version
  • X-AspNetMvc-Version

I set off to discover how to remove this configuration vulnerability from an ASP.NET Web API application running on Windows Azure.

Create a simple ASP.NET Web API application

Start Visual Studio 2012 as Administrator (we’ll need elevated privileges later when running the Windows Azure Emulator).

Create a new project with File > New > Project and select ASP.NET MVC 4 Web Application. Give the project a name of WebAPI and the solution a name of ExcessiveResponseHeaders. Click OK. Select the Web API template and click OK.

Right click on the WebAPI project in the Solution Explorer and select Add Windows Azure Cloud Service Project. A WebAPI.Azure project will be created with a WebAPI Role associated with the WebAPI Project. The WebAPI.Azure project will be configured as the startup project.

ExcessiveResponseHeaders project - Solution Explorer

The default Web API project created by Visual Studio will contain a simple Values Controller. Throughout this post I’ll be using the GET api/values REST endpoint which will simply return a list of 2 strings [ "value1", "value2" ].

ExcessiveResponseHeaders project - Values Controller GET method

Hit F5 and start up the project in the Windows Azure emulator.

Removing the Headers

Using Fiddler and issuing a GET api/values to the WebAPI application running on the Windows Azure emulator we can observe the following response headers:

  • Server: Microsoft-IIS/8.0
  • X-AspNet-Version: 4.0.30319
  • X-Powered-By: ASP.NET

Fiddler - Output for GET

No X-AspNetMvc-Version response header is observed since the api/values route is being managed by the WebAPI framework. If you issued a GET to the following URL: http://127.0.0.1:81/a/a you would observe the MVC header as the MVC framework routing would be brought into play:

  • X-AspNetMvc-Version: 4.0

To remove the Server header we add the following method and code to the Global.asax.cs file in the WebAPI project:

protected void Application_PreSendRequestHeaders(object sender, EventArgs e) 
{ 
  HttpContext.Current.Response.Headers.Remove("Server"); 
} 

To remove the X-AspNetMvc-Version header we add the following code to the Application_Start() method in the Global.asax.cs file in the WebAPI project:

To remove the X-AspNetMvc-Version header we add the following code to the Application_Start() method in the Global.asax.cs file in the WebAPI project:

Add code to Global.asax.cs

To remove the X-AspNet-Version header ensure that the Web.config has the following xml:

<configuration>
  <system.web>
    <httpRuntime enableVersionHeader="false" />
  </system.web>
</configuration>

To remove the X-Powered-By header ensure that the Web.config has the following xml:

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

Add config to web config

Hit F5 in Visual Studio again to start up the application with our changes. Using Fiddler and submitting a GET api/values to the WebAPI application now shows that the headers have been suppressed.

Fiddler - No Headers

Deploying this code to Windows Azure (http://pbwebapi.cloudapp.net) confirms that this solution works there too.

In Azure running the default Web API solution (before suppressing the headers):

Headers not suppressed in Azure

In Azure running the modified Web API solution (after suppressing the headers):

Headers suppressed in Azure

Is there a NuGet package for that ?

There always is … And its name is NWebsec.

Revert all the changes made previously in the Global.asax.cs and Web.config files. Right click on the WebAPI project and select Manage NuGet Packages … Search for NWebsec and install.

NWebsec NuGet Package

The installation of the NuGet package modifies the Web.config in the WebAPI project by adding a nwebsec sectionGroup and an entry in modules.

NWebsec web config updates

The X-Powered-By header is added by IIS and cannot be removed in the processing pipeline. Therefore NWebsec cannot remove it. To remove the X-Powered-By header ensure that the Web.config has the following xml:

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

To suppress all the other headers ensure that the Web.config contains the following xml:

<configuration>
  <nwebsec>
    <httpHeaderModule>
      <suppressVersionHttpHeaders enabled="true" />
    </httpHeaderModule>
  </nwebsec>
</configuration>

NWebsec configuration in web config

That was much better. We only had to add some configuration to the Web.config. There was no code involved.

The NWebsec package does not suppress the Server header but defaults it to a value of Webserver 1.0 – this value can be configured in the Web.config. All other headers are suppressed as can be seen via Fiddler.

Headers suppressed locally

Once the update is deployed to Azure (http://pbwebapi.cloudapp.net) it is confirmed that this solution works there too.

Headers suppressed in Azure

Scanning with ASafaWeb

Scanning the api/values REST endpoint of our default Web API application via the ASafaWeb analyser returns a warning about the same headers we observed via Fiddler.

ASafaWeb - Headers not suppressed

Scanning the api/values REST endpoint of our NWebsec enabled Web API application via the ASafaWeb analyser returns a warning about the same headers we observed via Fiddler.

ASafaWeb - NWebSec

Scanning the api/values REST endpoint of our manually configured Web API application via the ASafaWeb analyser returns a warning about a Server: Microsoft-IIS/8.0 header. This is not what we observed via Fiddler.

ASafaWeb - Manual

But wait … What is that URL that is being scanned ?
http://pbwebapi.cloudapp.net/api/values/elmah.axd ?

Sneaky ! That URL was resulting in a 404 being raised by IIS since the file did not exist. This was bypassing the processing pipeline and our attempts to suppress the headers.

Closing the 404 – Not Found hole

We’ll be continuing with the manual version of our suppressing headers code – I’m aiming to suppress all headers and the NWebsec package still sends down a Server header.

Again there is a NuGet package that comes to the rescue. NotFoundMVC automatically installs itself during web application start-up. It handles all the different ways a 404 HttpException is usually thrown by ASP.NET MVC. This includes a missing controller, action and route.

Right click on the WebAPI project and select Manage NuGet Packages … Search for NotFoundMVC and install.

NotFoundMVC NuGet Package Install

The NotFoundMVC package will make the following modifications to the Web.config file in the WebAPI project. The Error.cshtml placed under Views\Shared may be modified to provide customised 404 pages.

NotFoundMVC updates to Web Config

Deploying to Azure and scanning the api/values REST endpoint of our manually configured Web API application via the ASafaWeb analyser returns a PASS.

ASafaWeb - Pass

But wait – there’s more …

You’d think I would be happy with the PASS ! But I had seen something in one of the URLs attempted by the ASafaWeb analyser. It had thrown in an illegal character into the URL. So I tried the following URL locally:

HTTP.SYS Bad Request

Why is that Server header back ? And why is it now reporting Microsoft-HTTPAPI/2.0 ?

When you see a Server header value containing Microsoft-HTTPAPI instead of the IIS version it means the HTTP.SYS driver handled the request and it did not traverse all the way to the IIS user mode process.

So how do we get rid of that header now ? This header is being added right down at the kernel level. Time to break out the trusty regedit utility. Add a DisbableServerHeader REG_DWORD with a value of 1 to the following:

  • HKLM\SYSTEM\CurrentControlSet\Services\HTTP\Parameters

HTTP.SYS Registry Editor

This requires the HTTP.SYS service to be restarted. I battled with service dependencies but a reboot of my machine ensured the restart. Once that was done, the illegal URL no longer exposed the Server header.

HTTP.SYS Bad Request with suppressed header

And finally – modifying HTTP.SYS in Windows Azure

Trying the URL with the illegal character produced the same result in Windows Azure.

HTTP.SYS Server Header - Azure

To edit the registry on the web role in our cloud service in Windows Azure we’ll need to write a batch file. Right click the WebAPI project and click Add > New Item … Add a Text File with name Configure_HTTP.SYS.cmd and populate with the following:

@echo off
setlocal
set regpath=HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP\Parameters
reg query "%regpath%" /v "DisableServerHeader"
if errorlevel 1 (
   reg add %regpath% /v DisableServerHeader /t REG_DWORD /d 00000001
   shutdown /r /t 0
) 

This will add the registry entry if it does not exist and reboot the instance. This will only occur whenever the instance is re-provisioned as the registry entry will then no longer be set.

Make sure that the Build Action is set to None and the Copy to Output Directory is set to Copy always for the batch file.

Add command to project

Ensure that the batch file is configured as a startup task and is run with elevated privileges. Add the following xml to the ServiceDefinition.csdef file in the WebAPI.Azure project:

<Startup>
  <Task commandLine="Configure_HTTP.SYS.cmd" executionContext="elevated" />
</Startup>

Add to ServiceDefinition.csdef

Deploying to Azure and trying the URL with the illegal character now results in all headers being suppressed.

HTTP.SYS Suppressed Server Header - Azure

Conclusion

With a bit of work you can suppress all the headers in your ASP.NET application running in Windows Azure.

Be mindful though, that removing these excessive headers is not a silver bullet that will magically make your web application 100% less likely to be attacked. But by adding in these additional layers you at least can exclude attackers that look at specific response headers to determine whether or not you are an interesting target.






Published at DZone with permission of Paul Bouwer, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)