Why you need a Content Security Policy in your code

Matthew Mirzai
By Matthew MirzaiSenior Developer
5 minutes to read

Website security has been a hot topic for the last couple of years, and for good reason.

There’s been many major security breaches and data hacks but sometimes they’re not always obvious. Planting hidden scripts can achieve anything from mining bitcoins to harvesting user keystrokes. But the good news is that these are actually really easy to prevent with the help of Content Security Policy code.

Why do I need a Content Security Policy?

Think of a Content Security Policy (CSP) as a whitelist for approved website content. For every webpage you view, the back-end system will need to load some files. There’s two ways these files can be hosted:

  1. On the same internal server with a very, very low chance of being compromised or;
  2. Externally on the web which is often the point of compromise for a security breach.

Your browser doesn’t know what these files are for, just that they’re needed – so anything included with the files these is run as normal. Even if it’s malicious.

What does a Content Security Policy do?

In the website source code, a CSP will ask you for a list of internal and external files you want to include. If a file’s not on that list then it’s blocked.

If your site needs to load an external JavaScript file from Google (or another trustworthy source), any script trying to piggyback on top of it is immediately blocked and won’t run. 

A CSP is used to filter out everything from fonts and images to CSS – it’s comprehensive and quickly puts a stop to attacks of this nature.

How can we block malicious internal scripts?

But what if the file has been added as a reference from the source code itself, surely it has to be trusted then? This is true for browsers as it can’t differentiate between malicious and genuine code so both will run either way.

But CSP blocks inline scripts by default so the user has to manually allow them to run. How can we put a stop to these kinds of attacks? CSP hashes are the answer. 

When you’re adding a script, you have to wrap it around some <script> tags. If malicious code wants to embed itself, it will either add its own tags or add itself into an existing set. CSP hash puts a stop to this by breaking down all script tags on the page and converting it into a key (the default for CSP is using SHA-256 encryption). This key will change depending on what’s found within the script tags.

How do I add a key to my code?

Say we now have this key:

 

sha256-iSgJBLsSmSSlRW49LaowkHUZSMRa1IMy/MyyCdRXUJM=

We can add it to our CSP code as follows:

Content-Security-Policy: default-src 'self'; script-src 'sha256-iSgJBLsSmSSlRW49LaowkHUZSMRa1IMy/MyyCdRXUJM='

This essentially says we trust the contents of this script based on this key. If any extra code has been added which shouldn’t be there, the keys won’t match and nothing will run. This stops attacks in their tracks.

How to use nonces

But what about dynamic scripts that change based on an external factor, like the user’s location or the current time? CSP can even help with that using CSP nonces.

CSP nonces effectively work the same way as CSP hashes, except the key is generated dynamically as the page loads. This also means you need to attach the key to the script tags like this:

<script nonce="sha256-iSgJBLsSmSSlRW49LaowkHUZSMRa1IMy/MyyCdRXUJM=">...</script>

And now your dynamic scripts are safe.

It’s very easy to set up and is an incredibly effective countermeasure against many attacks your website is likely to encounter. It’s not the be all and end all though – you should still be enforcing other forms of security such as HTTPS and header protection.

We’ve been running CSP’s on our site builds as standard for a couple of years. Google has started enforcing it with their Chrome browser so you will start to notice other sites using both this and other security policies.

Nearly every modern browser supports CSP with Internet Explorer the only exception. For something that’s fairly easy to set up and maintain, the payoff is ridiculously good.

If you want to get going with this on your own site, I cannot recommend Report URI enough – it’s a fantastic tool and completely free.

comments powered by Disqus

Articles by Matthew Mirzai

Matt has 10 years experience in the development field and is a Senior Developer here at Enjoy Digital, specialising in Umbraco (and Mario Kart!).