Content Security Policy (CSP) is a built-in protection mechanism in web browsers that allows you to specify trusted sources for content such as JavaScript and allows you to block inline incudes. It can effectively stop attacks such as Cross-site Scripting and ClickJacking.
The settings are configured server side and given to the web browser via a server response header, the “Content-Security-Policy” header, here’s a simple example of one of these headers:
Content-Security-Policy: script-src 'self'; object-src 'self'
The header has a lot of options, but effectively it allows you to specify a resource type and then specify a whitelist of locations from which those resources can be loaded. So the above header is talking about script files and defining that only the same origin can be used to load resources by using the short name ‘self’, but we can whitelist sources easily using the following options:
‘none’ | Disallow all resource locations |
‘self’ | Same origin only |
* | Wildcard, allows any URL except data: blob: filesystem: |
domain.example.org | specific domain |
*.example.org | any subdomain |
https://domain.example.org | specific domain and protocol |
‘unsafe-inline’ | allow embedding of elements including script tags and handlers such as onfocus=, onerror= |
‘unsafe-eval’ | allows evaluated JavaScript, such as eval() |
data: | allow loading resources via the data: scheme |
We’re not only restricted to whitelisting sources for scripts, we can define where we can load scripts, images, videos, fonts, objects, all sorts. Here’s a few you might want:
default-src | Defines the default sources for directives which haven’t been given a more specific source list. So if you just specify this one it’ll set up the others for you, but you can specify default and then additional ones such as script-src and default-src will be used for all resource types other than scripts, which will use the more specific list given. |
script-src | Defines valid sources for scritpts |
style-src | Defines valid sources for CSS |
frame-ancestors | Defines which pages may embed this page as a <frame> or <iframe> |
A full list of directives can be found here: https://developer.mozilla.org/en/docs/Web/Security/CSP/CSP_policy_directives
Now you obviously want to configure your whitelist to be as restrictive as possible, but you don’t want to break any functionality you’ve forgotten about by blocking its source (such as analytics scripts for example!), so this requires a lot of testing. Thankfully there’s another header which can help:
Content-Security-Policy-Report-Only:
This header will simply log in the Chrome Developer Console any violations of the policy, but allow the execute to continue, you can also set up reporting, so the browser will send your server a list of violations, with a header configuration making use of the “report-uri” directive:
Content-Security-Policy: default-src https:; report-uri https://report.gracefulsecurity.com
Don’t forget though, that the reports are effectively user input, so you should ensure that you filter the input and ensure the application handles malicious input safely.
Violations are sent in JSON format and look something like this:
{ "csp-report": { "document-uri": "http://example.com/testing.html", "referrer": "", "blocked-uri": "http://example.com/main.css", "violated-directive": "style-src cdn.example.com", "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /csp" } }
A note on Browser Support
CSP is supported by all modern browsers, although it’s worth noting that the standard defines the header as:
Content-Security-Policy
But Internet Explorer uses:
X-Content-Security-Policy
So you might have to define both headers, to ensure the most compatibility possible!
Read More