The Untapped Power of Security Headers

HTTP HeadersUser-targeted attacks, such as XSS, often involve manipulating the server or browser into behaving in a manner not originally intended. While this has always been a serious risk, new HTML5 technologies enhance browser capabilities enough to make client-side attacks an increasingly inviting attack vector.

For a web developer, protecting the client has traditionally been limited to preventing client-side injection and browser manipulation. Beyond that, there was not much more that could be done other than helping users to make smart security decisions. But with the new features of HTML5 comes new ways to improve client-side security through security headers.

Security headers are HTTP response headers that direct the browser’s behavior to enhance a web site’s security. To prevent attackers from manipulating browser behavior, security headers allow you to be specific about your intentions for content served from your web site.

Some of these header specifications are fairly new or browser-specific and they are not universally implemented across all browsers, but there is enough support that now is the time to start implementing these in some form.

If you aren’t already aware of the various security headers available, I thought I would do a quick summary:

 

Content Security Policy (CSP)

CSP is a least privilege approach to security that uses the Content-Security-Policy, X-Content-Security-Policy, or X-WebKit-CSP headers (depending on your browser) to define exactly which resources the browser is allowed to load for any particular page and from where they can be loaded. So if you want a certain document to only be able to load scripts from a specific server you can now specify that through the CSP header. CSP currently allows you to set restrictions for loading scripts, objects, styles, images, media, frames, and fonts. By default, CSP also blocks eval(), inline scripts, inline CSS styles, and data URIs. It further allows you to provide a reporting URL to help identity possible emerging threats which is especially helpful for DOM-Based XSS attacks that are normally difficult to detect.

At this point, CSP specifications vary between browsers and support in mobile browsers is somewhat limited. On top of that, many web sites use inline code and make use of the eval() function so initially full implementation is likely not possible. Still, even the most basic CSP implementation can cripple a large number of client-side attack vectors and is well worth the effort to implement.

In short, CSP is already a powerful tool for limiting client-side attacks and it looks to be an even more promising technique as the specification evolves.

Here is a demo page that shows how CSP can affect page elements (hint: use your browser’s developer panel to view messages about blocked elements).

Some tips for using CSP:

  • Use SSL to prevent tampering of CSP headers.
  • Set very specific origins for each type of resource rather than using the * wildcard.
  • The browser will fall back to a default source if none is provided so use the default-src directive to set a blanket policy.
  • When using a reporting URL, make sure you take precautions to prevent that from introducing new vulnerabilities.

Other useful CSP Resources:

 

Cross-Origin Resource Sharing (CORS)

CORS doesn’t directly increase security, it actually reduces it. But it allows you to do so in a controlled and granular manner to limit exposure to attack. Normally same-origin policy only allows a script to access resources from the same host. For those times when you need to access resources from other hosts, you can limit access for your specific needs. The CORS-related headers are:

Access-Control-Allow-Origin
Access-Control-Allow-Credentials
Access-Control-Expose-Headers
Access-Control-Max-Age
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Request-Method
Access-Control-Request-Headers
Origin

Tips for using CORS:

  • Never allow GET or OPTIONS requests to modify data.
  • Use the Access-Control-Allow-Origin headers as needed on a per-resource basis, rather than for the entire domain.
  • Only use Access-Control-Allow-Origin: * for publicly-accessible static resources that do not include sensitive information or modify data.

 

HTTP Strict Transport Security (HSTS)

HSTS uses the Strict-Transport-Security header to tell the web browser to only server resources from your site using HTTPS. Once specified, the HSTS header will cause the browser to upgrade all HTTP requests to HTTPS. It also prevents users from overriding invalid certificate errors for your site.

Tips for using HSTS:

  • The browser only needs to see the header once so you generally only need to set it for documents, not for the resources loaded by those documents.
  • Because the browser will only honor HSTS headers delivered via HTTPS, you must still configure your site to redirect all resources to HTTPS so the browser gets the HSTS header.

 

X-Frame-Options

The X-Frame-Options header allows you to direct browsers not to embed a document in a frame or to only embed it from documents of the same origin. The purpose of this is to reduce exposure to clickjacking attacks. Although this header does not guarantee your content will never appear in a frame on all clients, all major web browsers will honor this and browsers are the primary mechanism for clickjacking attacks. Most web sites should implement this at least for documents of the same origin.

The X-Frame-Options header provides for two options: Deny, to block all frame embeds, or SameOrigin, to only allow the page to embed in frames from the same server.

 

IE-Specific Headers

Internet Explorer provides support for additional security headers not found in other web browsers. Although these protections only protect a portion of your user base, even a small decrease of attack surface is worth the effort.

X-Content-Type-Options: NoSniff

One IE-specific feature, the X-Content-Type-Options: nosniff header prevents the browser from improperly identifying MIME types. For example, it will not load a script unless the server specifically identifies it as a script through the Content-Type response header.

X-Download-Options: NoOpen

This header allows a web server to specify that a document should never be loaded in the browser and must be saved locally to view. This helps to prevent the browser from loading scripts and other potentially dangerous resources.

X-XSS-Protection

The X-XSS-Protection header,  allows you to control behavior of the IE XSS Filter which protects from a number of reflective XSS attacks. Normally XSS protection is enabled by default in Internet Explorer, but this header provides  you with two additional options to control this filter.

First, if the filter causes problems with your web site and your site is already well-tested for XSS vulnerabilities, you can disable the filter using this header:

X-XSS-Protection: 0

Second, you can make the filter more aggressive by completely blocking a page when XSS is detected rather than trying to simple filter out the attack. You can enable this with the header:

X-XSS-Protection: 1; mode=block

 

Implementation Strategy

The best thing about most of these security headers is that you generally do not need a full implementation to benefit from some of their protections. Although the ideal solution would be to coordinate security header implement between developers and web administrators, developers can implement many of these headers on a limited basis via code. Even if you are unable to implement security headers right now, it is important for developers to be aware of these features to lay the groundwork for future implementation. Moving away from inline scripts and styles, for example, is a major task that must be undertaken to prepare full CSP deployment. Start making those changes now because these security headers will make eventually play a major role in client security.


8 Ways to Prepare for CSP

Cross-Site Scripting (XSS) is a critical threat that, despite widespread training, still plagues a large number of web sites. Preventing XSS attacks can get complicated but even a small effort can go a long way–a small effort that nevertheless seems to evade us. Still, developers are getting better at input filtering and output escaping which means we are at least headed in the right direction.

Handling input and output aren’t the only strategies available to us. Content Security Policy (CSP) is a HTTP response header that–when correctly implemented–significantly reduces exposure to XSS attacks. CSP is exactly what it’s name implies: a security policy for your web content.

CSP not only allows you to whitelist browser content features on a per-resource basis, but also lets you whitelist those features on a per-host basis.

CSP not only allows you to whitelist browser content features on a per-resource basis, but also lets you whitelist those features on a per-host basis. For example, you might tell the browser it can load scripts for a page, but only if they come from a specific directory on your own web server. CSP allows you to set restrictions on scripts, styles, images, XHR, WebSocket, EventSource, fonts, embedded objects, audio, video, and frames.

One powerful feature of CSP is that by default it blocks inline scripts, inline styles, the eval() function, and data: URI schemes–all common XSS vectors. The only problem is that’s where it starts breaking existing code and could be a major obstacle to its widespread adoption. This is an all-too-common problem with frameworks, code libraries, plugins, and open source applications. If you write code that many other people use and don’t start getting it ready for CSP, you kind of hold us all back.  CSP does allow you to re-enable blocked features but that defeats the purpose of implementing content security policies.

So getting to my point, here are some things developers can do to their code to at least get ready for CSP:

  1. Remove inline scripts and styles. Surely you already know that it’s a good practice to separate code from presentation, now’s a good time for us all to stop being lazy and separating our code.
  2. Ditch the eval() function. Another thing we’ve all known to avoid for quite some time, but it still seems to show up. Most importantly, if you are working with JSON, make sure you parse it instead of eval’ing it. It’s rare to find a situation where there are secure alternatives to eval, you’d might be surprised how creative you can be.
  3. Don’t rely on data: schemes. Most often used for embedding icons into your code, data: URI’s are a powerful XSS vector. The problem here isn’t using them yourself which normally is safe, it’s that attackers might use them so the best solution is to disable them altogether. On pages that don’t work with user input in any form, you are probably safe to keep data: URI’s enabled.
  4. Create an organized, isolated directory structure. Scripts with scripts, images with images. Keeping content separate makes fine-grained CSP policies so much easier.
  5. Document features needed for each file. A good place to document features required for each file is in the source code itself, such as in a PHPDoc comment. By doing this, when you implement CSP you can start with the most restrictive policy and add only necessary features.
  6. Centralize your HTTP response headers code. A centralized function to send required headers makes it easier to keep track of it all and avoid hard-to-debug errors later.
  7. Eliminate unnecessary and superfluous scripts. It’s sometimes hard to give up cool features for security, but good discipline here can pay off. This is a business decision based on your threat model, but it’s always a good question to ask when adding new stuff.
  8. Mention it whenever possible. Yes, you should be that person who talks about CSP; so much that people simply stop inviting you to meetings.

And if you aren’t quite sure about how CSP works, here is some recommended reading:

An Introduction to Content Security Policy

Preventing XSS with Content Security Policy Presentation

Content Security Policy 1.0 Spec

Browser Support

CSP at OWASP

CSP Playground

CSP Readiness