Pseudorandom Knowledge

Security in headers

Cross site scripting (XSS) attacks can be difficult to prevent when developing web sites. However, the browser can be recruited in this struggle by sending it the appropriate headers. This example shows how this might be setup in the web.config file of a simple HTTPS enabled ASP.NET site.

<configuration>
  <system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name="Content-Security-Policy"
          value="default-src 'none'; img-src 'self'; style-src 'self'; script-src 'self'" />
        <add name="X-Frame-Options" value="deny" />
        <add name="X-XSS-Protection" value="1; mode=block"/>
        <add name="X-Content-Type-Options" value="nosniff" />
        <add name="Strict-Transport-Security" value="max-age=31536000" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
  <system.web>
    <httpCookies httpOnlyCookies="true" requireSSL="true" />
  </system.web>
</configuration>

Content-Security-Policy tells the browser where content should be allowed from. In this example only images, style sheets and script files from the same origin as the page are allowed. Everything else is blocked, including inline scripts and styles. Other content that can be controlled are fonts, media, plugins, connections and frames. Internet Explorer lacks support for this header.

X-Frame-Options provide the reverse control over frames. While Content-Security-Policy controls frames within the page this header controls the page within frames. In other words it can stop your page from being embedded inside someone else’s website.

X-XSS-Protection controls how Internet Explorer handles expected XSS attacks. This filter is already active by default but can be told to block pages completely instead of trying to sanitize them.

X-Content-Type-Options with its only valid option nosniff tells Internet Explorer to stop guessing MIME types and instead trust the server to set the content type correctly.

Strict-Transport-Security tells the browser that this host should be accessed via HTTPS. It is ignored when returned over HTTP. The normal use case for this header is to redirect users arriving via HTTP to HTTPS and return this header to tell the browser to connect directly via HTTPS in the future. This is not supported in Internet Explorer.

The last setting in the example tells ASP.NET to send cookies with the HttpOnly and Secure attributes. Together these tell the browser to only transmit the cookie over HTTPS and not expose it to client side scripts. Take care that you only access the server via HTTPS when using requireSSL because the ASP.NET session identifier will be recreated when the session cookie is not present in the request.