Your website needs a CSP. Here’s why

Here’s a scenario:

  1. You create a website and make it available online.
  2. Your website ends up getting hacked (it happens frequently, by the way..)
  3. The nefarious party is able to inject some malicious javascript into one of your pages.
  4. A legitimate user visits your website and is redirected to a phishing page as a result of the work done by an attacker.
  5. The user attempts to log into the page thinking it’s your website and ends up getting all of his credentials stolen.

This is not good – nobody wants their website to be hacked and getting their credentials stolen – but it happens. In fact, such events are unfolding constantly, and websites getting breached left, right and centre were the force behind the idea for me to establish BreachDirectory.

Such events can unfold differently too. I’ll start from the third stage:

  1. The nefarious party is able to inject some malicious javascript into one of your pages.
  2. A legitimate user visits your website and browses it as usual.

See any differences here? The user did not get his credentials stolen because the malicious payload did not execute – it violated the CSP that was present on your website.

CSP? What CSP?

CSP stands for Content Security Policy. The primary goal of using a Content Security Policy on your website is to mitigate certain types of attacks, including Content Injection and Cross-Site Scripting (XSS).

Content Security Policy can be enforced by sending an HTTP response header. The policy itself can contain one or more CSP directives – these are the “rules” that your browser must abide by.

CSP Directives

There are more than 20 CSP directives that can be used. I’ll mention a few of them:

  • script-src – defines valid sources that the browser can load JavaScript from
  • style-src – defines valid sources for stylesheets
  • img-src – defines valid sources for images
  • require-sri-for – allows website developers to ensure that Subresource Integrity is used for scripts and / or styles
  • upgrade-insecure-requests – instructs the user agent to upgrade all HTTP requests to HTTPS before fetching them
  • report-uri – instructs the user agent to report Content Security Policy violations. (Will be deprecated in CSP 3. See report-to)
  • report-to – allows developers to define the reporting group that reports should be sent to.

Building the policy

A basic Content Security Policy might look something like this:

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

If one of your pages contains this HTTP response header, the browser would only be allowed to load content from the same website as the page returning the header. This means that you wouldn’t be able to load content from third-party Content Delivery Networks such as CloudFlare or Bootstrap. If you would want to load scripts from them you could enforce the following header:

Content-Security-Policy: default-src ‘self’; script-src ‘self’ cdnjs.cloudflare.com

This header will tell the browser that by default, it can load any type of content from your domain, but scripts can only be loaded from cdnjs.cloudflare.com. If you load a script that isn’t from there while the above HTTP header is in place, the browser would refuse to load it:

What about this code block? It isn’t malicious, so it should be allowed to run, right?

<script>
$(“#button”).click(function() {
alert(“You clicked a button.”);
});
</script>

Wrong – that’s blocked too:

There are a few ways a website developer could get the above code block to run:

  1. An “unsafe-inline” keyword needs to be specified in the header
  2. The entire code block can be white-listed by specifying a “nonce” (a number, that can be only used once)
  3. A developer can also specify a hash.

The “unsafe-inline” keyword allows any script to run – if your website would get hacked and the attacker would want to redirect users to a malicious website by injecting some javascript into one of your pages, he could do that. This isn’t very good so lets have a look at the second option, now we will use a slightly different policy – we will add a nonce:

Content-Security-Policy: default-src ‘self’; script-src cdnjs.cloudflare.com ‘nonce-ZDE0OTIyMzcwMjNiZTYyMjY2MTUzZjQ3NmRlYTczYzU=’

A nonce allows you to white-list an entire code block:

<script nonce=”ZDE0OTIyMzcwMjNiZTYyMjY2MTUzZjQ3NmRlYTczYzU=”>
$(“#button”).click(function() {
alert(“You clicked a button.”);
});
</script>

Note that the nonce in the header is exactly the same as the nonce in the script tag: it has to be the same, otherwise our script won’t execute. But hey, there’s also a third option, so we should have a look at that too – the browser told us that in order for the script to execute, the following policy can be used:

Content-Security-Policy: default-src ‘self’; script-src cdnjs.cloudflare.com ‘sha256-UEDzDzSiQoZnNVNOKXXr37XeW1TYAb7S7jtVORuIUTk=’

This allows developers to run the above code block, but if the contents of the code block would change, the hash would be different too – the browser would refuse to load the script.

Other uses of CSP

Content Security Policy can also be used to ensure that Subresource Integrity (SRI) is used across all of the styles and scripts in your website – there’s a header that might help you achieve this:

Content-Security-Policy: require-sri-for script style;

That’s it! It’s that simple.

When using CSP, a browser can be forced to upgrade any HTTP request to HTTPS before issuing it (to accomplish this, you can use upgrade-insecure-requests) or you could block all mixed content entirely by using a directive called block-all-mixed-content – whatever floats your boat.

After you’ve deployed Content Security Policy to your website, it would be a good idea to check if you’ve done so correctly: Scott Helme’s tool called SecurityHeaders should help you accomplish that.

Logging violations

There’s little use of a CSP if you don’t record what was violated. You need to tell the policy where to send the reports too – use the “report-uri” directive:

Content-Security-Policy: default-src ‘self’; script-src ‘self’ cdnjs.cloudflare.com; report-uri https://domain.com/reporturi.php

This will instruct the user agent to report attempts to violate the Content Security Policy and send them to a specified URI. The directive is deprecated though – since CSP 3, “report-to” should be used instead.

Conclusions

  • Content Security Policy (CSP) is important – it prevents multiple types of attacks by allowing a developer to specify the locations where the browser can load resources from via an HTTP header.
  • There are a lot of CSP directives that can be used – I have only mentioned a few of them.
  • Using CSP? Enable reporting – it’s essential.

Before enforcing the policy, make sure to test it in a “report-only” mode for some time though – this way a developer could see the violation reports but nothing would break on their website. An HTTP response header called “Content-Security-Policy-Report-Only” makes this possible by monitoring the effects of the policy without applying them.

Colors

View Comments

  • Concerning Breach Directory, are you aware of the ancient Zone-H? I know it's just a "defacement mirror" site, but if a website has been defaced, there's a high chance the database was compromised as well.

    • Yes, I am aware of Zone-H. It is true that some of the websites that have been archived there had their databases compromised at some point, but as far as I am aware, only a small percentage of the sites archived there have their databases available publicly.

  • What i don't realize is in fact how you are now not
    actually a lot more neatly-liked than you might be right now.

    You are very intelligent. You understand therefore significantly in the case of this subject, produced
    me in my view imagine it from so many varied
    angles. Its like men and women don't seem to be involved until it is something to
    do with Woman gaga! Your own stuffs nice. All the time maintain it up!

  • I would like to use the ability of saying thanks to you for that professional instruction I have continually enjoyed checking out your site.
    I am looking forward to the particular commencement of my
    college research and the complete preparing would never
    have been complete without browsing your website.
    If I may be of any help to others, I might be
    ready to help by means of what I have discovered from here.

  • What's upp to every body, it's my first go to see of this blog;
    this weblog includes remarkable and genuinely
    fine material in support of readers.

  • I'd constantly want to be update on new posts
    on this site, saved to favorites!

  • Excellent site you have here but I was wondering if you knew of any user discussion forums that cover
    the same topics discussed here? I'd really love to be a part of group where
    I can get responses from other knowledgeable individuals
    that share the same interest. If you have any recommendations, please let me know.
    Kudos!

  • Hi there! This article couldn't be written any better!
    Reading through this article reminds me oof my previous roommate!
    He continually kept talking about this. I'll send this post to him.
    Faairly certain he's oing to have a good read. Many thanks for sharing!

  • This piece of writing will assist the internet
    viewers for creating new weblog or even a blog from start to end.

  • I just wanted to thank you once more for this amazing web-site you
    have developed here. It truly is full of ideas for those who are genuinely interested in this kind of
    subject, in particular this very post. You really are all so
    sweet plus thoughtful of others plus reading your blog posts is an excellent delight in my experience.
    And thats a generous treat! Dan and I are going to have excitement
    making use of your guidelines in what we should instead do in the near future.

    Our checklist is a kilometer long which means your tips will definitely be put
    to excellent use.

  • Its like you read my mind! You appear to know a lot
    approximately this, such as you wrote the e-book in it or something.

    I think that you simply can do with a few p.c.
    to pressure the message home a bit, however other than that, this is magnificent
    blog. A great read. I'll definitely be back.

Share
Published by
Colors
Tags: Security

Recent Posts

Messed Up at a Conference? You‘re Not Alone – Lessons for Speakers in Remote Conferences

This blog will walk you through some lessons for conference speakers who speak remotely no…

2 months ago

OWASP Mobile Top 10 Part 2: Insecure Data Storage

Insecure data storage is the second vulnerability in the OWASP Mobile Top 10 list. Insecure…

3 years ago

OWASP Mobile Top 10 Part 1: Improper Platform Usage

The improper platform usage vulnerability is the first vulnerability in the OWASP Mobile Top 10.…

4 years ago

What is the OWASP Mobile Top 10?

If you ever heard of web application security, you probably heard of OWASP. And if…

4 years ago

The Basics of MySQL Security

If you have ever built a website, chances are you took care of security. Securing…

4 years ago

Build Stuff 2019 Retrospective

It's November. For some developers it's just an ordinary month - for some of them…

5 years ago