Content Security Policy (CSP)

Content Security Policy (CSP)

Date: 2016-12-20 12:29:24

Content Security Policy (CSP) is the HTTP header we mentioned earlier in our Advanced Clickjacking Attacks article that can be used as defense in depth to mitigate certain types of attacks, especially Cross-site scripting (XSS) and Clickjacking. This article will explain when and how to use CSP.

1. Basics on CSP

CSP defines from which sources a browser may load additional resources for a given webpage. As such, it can be used to tighten the same origin policy and mitigate attacks that try to include malicious content.

A correctly configured CSP can defend against most XSS vulnerabilities if the user uses a browser which supports CSP, as it is no longer possible to inject JavaScript code into the webpage itself, or to include scripts from forbidden origins. This means an attacker would need to be able to upload JavaScript files onto a permitted domain to gain XSS, or otherwise be left with a less severe HTML injection.

Additionally, CSP can defend against Clickjacking. While most browsers do support X-Frame-Options which also defends against Clickjacking, it was never formalized in a standard and may thus not be supported by all future browsers. It also provides less fine-grained control than CSP.

2. How to use CSP

To use CSP, the application needs to send an additional HTTP header in each reply. HTTP header can either be set by the webserver to apply to all pages, or by the web application itself, if more fine-grained control is required.

Content-Security-Policy: [policy]

A good starting policy which prevents loading additional resources from all other origins and prevents the execution of inline styles and scripts is:

Content-Security-Policy: default-src 'self'

Additional origins can be added if needed:

Content-Security-Policy: default-src 'self' example.com

It is also possible to specify that specific resources - images in this case - can be loaded from other origins:

Content-Security-Policy: default-src 'self'; img-src https://example.com

It should be noted though that it may be possible to bypass the CSP by including JavaScript in images. If it is required that untrusted image sources are allowed, X-Content-Type-Options: nosniff should be set as well.

3. Preventing Clickjacking with CSP

By specifying frame-ancestors 'none', any framing of the page is prevented, thus preventing Clickjacking. As with all CSP directives, it is possible to allow specific origins, such as using self to allow framing from the same origin.

3. CSP Pitfalls

As CSP restricts what resources may be loaded and executed, applying a CSP to an existing application may break certain parts of it. Because of the substantial added security benefit of CSP, it is recommended to fix these issues instead of doing without a CSP, especially as they are best-practices anyways.

Dealing with inline scripts

The default 'self' setting does not allow the execution of inline script or styles. Blocking inline scripts means that anything is blocked that allows entering a JavaScript context, such as script tags, event attributes, or the javascript URI scheme. It is possible to allow these by setting unsafe-inline, nonce-source, or hash-source. However, though they are specified in the RFC, neither is completely supported by all browsers. Because of this, extensive testing is recommended when using inline scripts.

However, allowing inline scripts via unsafe-inline removes many of the benefits of a CSP. Instead of using inline scripts, scripts should be included from an external file. Instead of using event attributes, external scripts should add these via addEventListener.

If it is not possible to remove inline scripts and not all old browsers need to be fully supported, using hash-source or nonce-source over unsafe-inline is recommended as it provides more security. While unsafe-inline allows the execution of all inline scripts, hash-source defines specific script blocks which may be contained and executed inline. It does this by defining the source as the hash value of the JavaScript code that is to be allowed. Similarily, nonce-source allowes the execution of all JavaScript code that is in script blogs tagged with the nonce given in the CSP. It is important that this nonce is regenerated for each request or session, as an attacker could otherwise inject script blocks with the given nonce.

Dealing with restricted functions

By default, CSP disables the use of the JavaScript functions eval as well as setInterval, setTimeout, and new Function with strings as arguments. To allow these, unsafe-eval must be specified:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-eval'

4. Testing CSP

As a newly added CSP to an existing application may break functionality - especially inline scripts - it may be sensible to first only report violations instead of blocking them. To do this, the Content-Security-Policy-Report-Only header can be used instead of the Content-Security-Policy header:

Content-Security-Policy-Report-Only: [policy]; report-uri example.com/report

Reporting CSP violations

When using Content-Security-Policy-Report-Only the reports must be send to a specific script using the report-uri directive. Even when not using report-only, it may make sense to enable the report-uri directive to discover bugs because of incorrectly applied CSP or code, or to discover attempted or successful attacks which try to violate the CSP.