Trust is the fundamental currency of the internet. You trust your service provider that they’ll continue to maintain your internet access. Your developers trust your architecture provider when they say that your servers will stay up. Customers trust that you’re safely securing your data. They also trust that when they visit your website, what they’re seeing is what you want them to see.
A common attack vector against public websites is injecting content which claims to be from that website. In reality, it’s content that’s hosted elsewhere. Once it’s loaded and executed on a customer’s computer, it likely takes advantage of them in some way. Those attackers might use XSS attacks, injecting malicious iFrames or Clickjacking.
Obviously, these kinds of attacks erode your customers’ trust in your organization. Those attacks often confuse them, which leads to abandoning a shopping cart or an uptick in support tickets. The monetary costs for these attacks have a real impact on your business.
How does a Content Security Policy help?
Thankfully, there’s a tool your team can use to prevent these kinds of attacks. Known as a Content Security Policy, it’s a mechanism built directly into web browsers which limits what the browser will do on your website.
When your website includes a Content Security Policy, the browser inspects every item that the website’s HTML requests. If the CSP doesn’t permit the origin of an image, the browser doesn’t download it. If the CSP blocks the origin of a script, the browser doesn’t execute it. You define a list of rules, and anything which doesn’t match that list of rules is eliminated before it reaches a user’s computer.
Obviously, this kind of protection is a powerful deterrent against website-damaging attacks. Instead of being annoyed by popups or exposing their credentials to an attacker, your customers get the experience you’ve intended.
Using a CSP to prevent packet sniffing
One uncommon benefit of a content security policy is that you can force the browser to encrypt communications with your server. While you might provide an HTTPS endpoint for your users, some browsers won’t connect to HTTPS by default. Others will still connect to HTTP, even if HTTPS is the default. Using the content security policy, your team can define the acceptable ways to connect your server. If you limit the acceptable communications channels to encrypted ones, you can ensure that your communication with users is secure. Secure communications are another important piece of making sure that your customers can trust your website. What’s more, they’re an important piece that help you ensure you can trust your customers.
Enforcing encryption standards using CSP doesn’t just extend to communication, either. Using standard CSP directives, you can ensure that the browser will also encrypt things like cookies when they’re stored on a user’s machine. Savvy attackers who gain access to a user’s computer will commonly examine stored cookies to look for things like stored passwords, user IDs, or session identifiers. Encrypting your cookies prevents these users from being able to shortcut common ATO attacks.
How can I set up a Content Security Policy?
Setting a Content Security Policy for your webserver is shockingly simple. It’s easy to do in ASP.NET MVC, Ruby on Rails, or Django. If you program in a different language or framework, a short google will likely lead to a quick tutorial about how to set it up in your workflow. If there isn’t a simple answer in your application programming language, it’s pretty simple to set up in Apache or Nginx, too.
It’s likely that the real challenge of setting a Content Security Policy won’t actually be technical. Technically, it amounts to a few lines of code.
Instead, the real challenge of setting a Content Security Policy is likely to be in cataloging all of the content your website delivers. Modern websites include a variety of scripts and stylesheets. Often, these come from a variety of different sources, many of which might not be your website
Let’s take a look at Facebook’s Content Security Policy to see the how detailed they can be:
content-security-policy: default-src * data: blob: 'self';script-src *.facebook.com *.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* 'unsafe-inline' 'unsafe-eval' blob: data: 'self';style-src data: blob: 'unsafe-inline' *;connect-src *.facebook.com facebook.com *.fbcdn.net *.facebook.net *.spotilocal.com:* wss://*.facebook.com:* https://fb.scanandcleanlocal.com:* attachment.fbsbx.com ws://localhost:* blob: *.cdninstagram.com 'self' chrome-extension://boadgeojelhgndaghljhdicfkmllpafd chrome-extension://dliochdbjfkdbacpmhlcpmleaejidimm https://api.mapbox.com https://*.tiles.mapbox.com https://services.digitalglobe.com;block-all-mixed-content;upgrade-insecure-requests;
You’ll notice that Facebook allows images and scripts from a variety of sources that aren’t facebook.com. It’s up to Facebook engineers to identify which sources are safe and define those within their CSP. This is the hard work of adding a CSP to your site.
How can I make sure my CSP doesn’t break my site?
Like we noted above, messing up your Content Security Policy has harsh side effects. Your website breaks completely. You’re leaving your users out in the cold. These negative side effects scare away some companies. They ship one bad Content Security Policy, the website breaks, and they throw the baby out with the bathwater. Obviously, this isn’t a wise tactic. Luckily, browsers have another built-in tool to make sure that your website doesn’t break when you enable a CSP. It’s the Report Only directive.
The Report Only directive does exactly what it says. Instead of stopping parts of your website from working, the browser logs errors to the browser console. By adding a Report Only directive, your team can pick through each violation of the Content Security Policy and fix them one by one. If you’re not a senior leader of your organization, this directive can be a real life saver. Instead of deploying an update that knocks your website offline, you can ensure that there are no problems before you turn on your CSP.
How can I make sure my CSP is actually useful?
It’s important to make sure that when your team adds a CSP to your website, you’re doing useful work. To be useful, you need to both set up your CSP properly and maintain it. Once your CSP is in place, you need to monitor and maintain it whenever your website changes — be it new assets, new tracking tools, new ad platforms, and so on. It’s crucial to implement a solution to ensure that your CSP remains up-to-date and enables you to add or remove assets as your website changes.
What are the valid CSP Headers?
Let’s take a look at some of the most common CSP headers and what each of them does, so you know which you’ll need on your site.
- default-src: This is a catchall header which indicates where items can come from. It only applies for attributes where you don’t set a specific value. Often, you want to set this to ‘self’ . This setting prohibits loading items from external sources unless you specifically allow them with other headers.
- script-src: The list of acceptable source locations to load client-side scripts. Correctly defining this list is a big security boost for your customers.
- img-src: The list of acceptable source locations for images.
- media-src: A list of acceptable source locations for rich media like video and audio.
- object-src: A list of acceptable source locations for plugins. Unless your website is specifically designed to use legacy applets like those for Internet Explorer 6, this should be set to ‘none’ .
- manifest-src: A list of acceptable source locations for web manifests. Web manifests are used by users of Progressive Web Applications to download websites and run them like native mobile apps.
- frame-ancestors: A list of acceptable URL locations which this website can load in an iFrame.
- form-action: A list of acceptable URL target locations where the website can send form data. It’s most likely that you want this value set to ‘self’ as most websites only submit their form data locally. This property is not covered by default-src above, so make sure you set it.
- plugin-types: The list of plugin types that can be loaded from the locations in object-src. Likely that you also want to set this to ‘none’ .
- base-uri: The list of URLs that can be used in HTML base tags on your site.
A CSP is a gatekeeper for your website
That’s the simplest way to describe a content security policy. It acts like a gatekeeper for your website. A good CSP limits where data on your site can come from, and what scripts can be executed. Configuring and maintaining a good content security can be a bit of work, especially if your site has been online for a while or changes with any frequency. That time pays for itself though, whether via manual effort or good tooling, through the trust of your customers and time saved troubleshooting website security issues. If your team has been considering adding a CSP to your site, they’re a powerful tool for protecting against XSS and click-jacking, adding an additional layer of defense and improving your overall site security posture.
Eric Boersma wrote this post. Eric is a software developer and development manager who’s done everything from IT security in pharmaceuticals to writing intelligence software for the US government to building international development teams for non-profits. He loves to talk about the things he’s learned along the way, and he enjoys listening to and learning from others as well.