Response header updates for PCI Compliance

Server and Scripting Response Headers

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.  The response headers can be viewed in a browser using dev tools like Chrome Developer Tools as in the below image.


Removing the headers is fairly straight forward.  With X-Powered-By and X-AspNet-Version being disabled via web.config and X-AspNetMvc-Version being disabled in a projects globa.asax(.cs) file.


Server

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


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

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 the 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 header would be



Additional Response Headers

Additional response headers maybe 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.  And extra care and review may be required versus the headers detailed in the first section of the article.