Boy Baukema

Boy Baukema
23 januari 2014


What started as a dream for a worldwide library of sorts, has transformed into not only a global repository of knowledge but also the most popular and widely deployed Application Platform: the World Wide Web.
The poster child for Agile, it was not developed as a whole by a single entity, but rather grew as servers and clients expanded it’s capabilities. Standards grew along with them.

While growing a solution works very well for discovering what works and what doesn’t, it hardly leads to a consistent and easy to apply programming model. This is especially true for security: where ideally the simplest thing that works is also the most secure, it is far too easy to introduce vulnerabilities like XSSCSRF or Clickjacking.

Because HTTP is an extensible protocol browsers have pioneered some useful headers to prevent or increase the difficulty of exploiting these vulnerabilities. Knowing what they are and when to apply them can help you increase the security of your system.  

1. Content-Security-Policy

What’s so good about Content-Security-Policy?

How would you like to be largely invulnerable to XSS? No matter if someone managed to trick your server into writing alert(1);, have the browser straight up refuse it?

That’s the promise of Content-Security-Policy. 

Adding the Content-Security-Policy header with the appropriate value allows you to restrict the origin of the following:

  • script-src: JavaScript code (biggest reason to use this header)
  • connect-src: XMLHttpRequest, WebSockets, and EventSource.
  • font-src: fonts
  • frame-src: frame ulrs
  • img-src: images
  • media-src: audio & video
  • object-src: Flash (and other plugins)
  • style-src: CSS

So specifying the following:

Content-Security-Policy: script-src ‘self’

Means that script files may only come from the current domain or from (the Google JavaScript CDN).

Another helpful feature is that you can automatically enable sandbox mode for all iframes on your site.

And if you want to test the waters, you can use use the ‘Content-Security-Policy-Report-Only’ header to do a dry run of your policy and have the browser post the results to a URL of your choosing.

It is definitely worth the time to read the excellent HTML5Rocks introduction.

What’s the catch

Unfortunately Internet Explorer (IE) only supports the sandbox mode, and with a ‘X-’ prefix no less. Also Android support is pretty new (4.4).

And of course it can’t protect against all XSS, if you generate your JavaScript dynamically (a bad idea, but not uncommon in practice) someone may still trick your server into generating bad JS.

But, including it does no harm and will protect users on Chrome, Firefox and iOS.

Where do Content-Security-Policy work?

Can I Use contentsecuritypolicy? Data on support for the contentsecuritypolicy feature across the major browsers from

Where do I learn more about Content-Security-Policy?

HTML5Rocks has an awesome introduction. Other than that, the W3C spec is quite readable.

2. X-Frame-Options

What’s so good about X-Frame-Options?

Stop Clickjacking with one simple header:

X-Frame-Options: DENY

This will cause browsers to refuse requests for framing in that page.

Supplying the value ‘SAMEORIGIN’ will allow framing only from the same origin and ‘ALLOW FROM’ will allow you to specify an origin (unsupported by IE).

What’s the catch with X-Frame-Options?

This header will be deprecated and it’s functionality will be moved to Content-Security-Policy 1.1 (which does not have the same level of support yet).
But until that has wider support, there is no reason not to use this header.

Where do X-Frame-Options work?

IEFirefoxChromeiOS SafariAndroid Browser


(data from Mozilla Developer Network)

Where do I learn more about X-Frame-Options?

Not much more to learn, but if you want some more information you can check out the Mozilla Developer Network article on the topic.

Also Coding Horror has an old (2009) but good article on Clickjacking / framing: We done been framed.

3. X-Content-Type-Options

What’s so good about X-Content-Type-Options?

Letting your users upload files is inherently dangerous, serving up files uploaded by users is even more dangerous and difficult to get right.  

This isn’t made any easier by browsers second-guessing the Content-Type of what you’re serving by doing Mime Sniffing.

The X-Content-Type-Options allows you to, in effect, say to browsers that yes, you know what you’re doing, the Content-Type is correct with it’s only allowed value: ‘nosniff’.

GitHub uses it, you can too.

What’s the catch with X-Content-Type-Options?

Only works for IE and Chrome, though depending on your audience that could be 65% of your visitors that you’re protecting.

Where do X-Content-Type-Options work?

IEFirefoxChromeiOS SafariAndroid Browser

8+- (bug 471020)1+–

Where do I learn more about X-Content-Type-Options?

FOX IT has an excellent article on MIME sniffing: MIME Sniffing: feature or vulnerability? and the IT Security Stackexchange has a dedicated question on this topic: Does X-Content-Type-Options really prevent content sniffing attacks?

4. Strict-Transport-Security

What’s so good about Strict-Transport-Security?

My online banking system uses HTTPS, providing authenticity (that yes, I really am connecting to my bank) and transport security (anybody snooping in would only see the encrypted traffic).

However, there is a problem with it…
When I type “” into the address bar of my browser, it will connect to plain old HTTP by default. It’s only if the server then redirects the user to HTTPS (which is a bad idea in theory, but a good one in practice) that I get my secure connection. Unfortunately this redirecting gives an attacker a window to play man-in-the-middle. To solve this the Strict-Transport-Security header was added.

The HTTP Strict-Transport-Security (HSTS) header instructs the browser to (for a given time) only use https. If for instance, you go to and (among others) it returns the following header:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Then even typing in will make the browser connect to

It will do this for as long as the HSTS header is valid, which in the case of the example is 1 year since the last response that sent the HSTS header. So if I visit the site once on January 1st 2013, it will be valid until January 1st 2014. But if I visit again on December 31st 2013 it will not only still be valid, it will reset the validity to be valid until December 31st 2014.

It only works on Chrome and Firefox for now. Your Internet Explorer users are still vulnerable. Never the less, it’s worth implementing as it’s an official IETF standard and the next IE should implement it real soon now…

Also you don’t want to implement this unless you’re using HTTPS, but why wouldn’t you be using HTTPS? Remember that HTTPS not only guarantees that your content (and the users content) will be encrypted and therefore uninterceptable, it also provides authenticity. Promising your users that yes, this content really came from you.

Why you should always use HTTPS is a different discussion and as evindenced by the fact that both that blog post and this one are not on HTTPS, still an uphill battle. But if you’re using HTTPS you should probably use HSTS too.

Where doe Strict-Transport-Security work?

Can I Use contentsecuritypolicy? Data on support for the contentsecuritypolicy feature across the major browsers from

Where do I learn more about Strict-Transport-Security?

The Mozilla Developer Network has a good article on it: HTTP Strict Transport Security.  

If you’re doing Symfony2 or Drupal

For Symfony2 take a look at the NelmioSecurityBundle and for Drupal check out the Security Kit module which allow you to specify all the aforementioned headers!

Hall of Shame: X-Requested-With

By default jQuery sends the X-Requested-With header. It was thought that the mere presence of this header could be used as a way to defeat Cross-Site Request Forgery. Surely no request with this header and a users session could be initiated by a third party as in a browser only XMLHttpRequest is allowed to set custom headers.

Unfortunately as the Ruby On Rails Ruby framework and the Django Python framework soon found out, while this is a good measure for defence in depth, it can not be fully relied on in the face of other third party plugins like Java or Adobe Flash.


Using the HTTP headers discussed above allows you to quickly and easily protect your users from XSS, Clickjacking, Mime sniffing vulnerabilities and Man-In-The-Middle attacks.

If you aren’t using these headers yet, now might be a good time to introduce them to your application or webserver configuration.

Keep your users safe out there.