Response header updates for PCI Compliance

Overview

To meet PCI compliance requirements, four response headers often have to be removed: Server, X-Powered-By, and in the case of a .NET (MVC) app, X-AspNet-Version and X-AspNetMvc-Version.

Removing them is fairly straightforward. X-Powered-By and X-AspNet-Version are disabled via web.config, and X-AspNetMvc-Version is disabled in a project's global.asax(.cs) file.

The response headers can be viewed in a browser using dev tools like Chrome Developer Tools, as in the image below.

Browser developer tools showing the response headers before the change, including X-AspNet-Version, X-AspNetMvc-Version and X-Powered-By

Server

The Server response header, in this case, is being passed by the load balancer rather than the web application. Because it is not used for basic site operation, it has been disabled globally.

You will still see a Server line listed in dev tools, but with no value after it. Nothing about the web server software is disclosed. There is no action for you to take, and no web.config change will remove the line itself.

X-Powered-By

The X-Powered-By header is removed via the customHeaders element:

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

X-AspNet-Version and X-AspNetMvc-Version

The ASP.NET version is disabled using the enableVersionHeader attribute:

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

To remove X-AspNetMvc-Version, MvcHandler.DisableMvcResponseHeader = true is added to the Application_Start event of the global.asax or global.asax.cs, as in the examples below:

protected void Application_Start()
{
    MvcHandler.DisableMvcResponseHeader = true;
}

or

Sub Application_Start()
    MvcHandler.DisableMvcResponseHeader = True
End Sub

Example web.config and response

An example web.config removing X-Powered-By and X-AspNet-Version would look like:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpRuntime enableVersionHeader="false"/>
  </system.web>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By"/>
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>

Then, along with the project update for MVC, the resulting response headers would be:

Browser developer tools showing the response headers after the change, with X-AspNet-Version, X-AspNetMvc-Version and X-Powered-By no longer listed

Verify it worked

  1. Open the site in a browser.
  2. Open developer tools (F12 in most browsers) and select the Network tab.
  3. Reload the page and click the first request in the list.
  4. Look at Response Headers. X-Powered-By and X-AspNet-Version should no longer be listed.

If they are still there, confirm the web.config is in the document root of the site and that it parses. A web.config with a syntax error is ignored or returns a server error rather than applying quietly.

Additional Response Headers

Additional response headers may be required, for example Content-Security-Policy (https://content-security-policy.com/), to set restrictions on how elements are loaded on the site. Because various headers may be required, a basic syntax example is:

<httpProtocol>
  <customHeaders>
    <add name="headerName" value="setting or directive" />
  </customHeaders>
</httpProtocol>

As an example, and not explicitly a guide, nopCommerce has many of these customHeaders set by default, as seen below:

<httpProtocol>
  <customHeaders>
    <add name="X-XSS-Protection" value="1; mode=block" />
    <add name="X-Frame-Options" value="SAMEORIGIN" />
    <add name="X-Content-Type-Options" value="nosniff" />
    <add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains" />
    <add name="Content-Security-Policy" value="default-src 'self'; connect-src *; font-src * data:; frame-src *; img-src * data:; media-src *; object-src *; script-src * 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline';" />
    <add name="Referrer-Policy" value="same-origin" />
    <add name="Permissions-Policy" value="accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=*, usb=()" />
  </customHeaders>
</httpProtocol>

Note that setting these customHeaders can have unintended consequences on what elements are being loaded on the site. Extra care and review may be required, more so than for the headers detailed in the first section of this article.

Related Articles