The Content Security Policy (CSP) has been a separate checkpoint for our Web Application Penetration Tests since September 2015. One of the first projects so tested is emblematic of the acceptance and implementation of CSP in general. In that project, multiple cross-site scripting (XSS) vulnerabilities were found. Along with strict input validation, we also recommended introduction of a CSP header as an additional measure. The developers implemented this and defined a policy. But the
Introduction of an effective Content Security Policy is a demanding task, one that should be carried out in accordance with web development. This article describes how CSP came about and how it is used in practice.
The first draft of the Content Security Policy Level 1 was published by the W3C Consortium on 15 November 2012. Browser vendors initially implemented it as an experimental function with the header
The goal of CSP is to provide both web developers and web server administrators with a tool for mitigation of injection vulnerabilities. When this kind of policy is defined, the web browser is informed which web application resources will be loaded and processed, such as images, style sheets (CSS) or scripts. Here, CSP should be considered a component of a defense-in-depth strategy rather than a replacement for input validation or coding of output.
X-Content-Security-Policy header is supported by Mozilla Firefox (since Version 4) and Microsoft Internet Explorer 10, but is already considered obsolete and should no longer be used. The
Content-Security-Policy header stands for CSP Level 1 and all further levels. It has been supported since browser versions Google Chrome 25, Mozilla Firefox 23, Safari 7 and Internet Explorer Edge.
Through directives, the policy can be tailored to the intended use of the web application. A directive is an instruction to a web browser how to handle several resource types. The
data: and one or more hosts/domains. The Content Security Policy Reference offers a good overview.
script-src, it became apparent that the existing source expressions were insufficient for real-life scenarios and thus inhibited implementation of CSP. With Level 2, published on 21 July 2015, the attribute
nonce was introduced to ensure additional flexibility. The following section discusses its use – and shortcomings.
frame-ancestors directive was also introduced with the aim of replacing the HTTP header X-Frame-Options. Here, the expression none equates to the value
DENY in the HTTP header. Veit Hailperin already explained this header in his article Inglorious Headers. For now we recommend a dual use strategy, set the policy and the header for it self because not all browsers support this CSP level.
strict-dynamic in the Working Draft for the CSP Level 3 dated 21 June 2016 attempts to solve this. As a further change, the directive
report-uri was renamed
Where CSP has not previously been used, we recommend starting with the following directive:
default-src “none”; script-src “self”; connect-src “self”; img-src “self”; style-src “self”;
To avoid recoding the entire website, the directive is usually expanded to include the expression
unsafe-inline. This means that the web application continues to function as usual, but is once again vulnerable to reflected or stored XSS attacks. This removes the benefit, or protective effect, of the policy.
script-src directive. Maintenance is no easy matter and in a worst-case scenario can even lead to a CSP bypass. This is vividly illustrated in solutions for the mini-challenge by Cure53 entitled “H5SC Minichallenge 3: Sh*t, its CSP!.
With the introduction of the attribute
nonce in CSP Level 2, there is now the option of use of embedded script elements. The principle behind
nonce is that a random nonce value is recorded in the
script-src directive. Ideally, this occurs through the web application itself. Every script element that sets this value in the
nonce attribute is then authorized. This means that legitimate script elements are executed, but XSS attacks are stopped.
nonce leads to a new problem as described below. The
nonce attribute is defined as:
Content-Security-Policy: script-src “nonce-i7bGtfs”
A library is then integrated into the website and correctly provided with the matching value in the
<script src=“https://cdn.example.com/script.js” nonce=“i7bGtfs”></script>
Because the correct value for
nonce is set, the integration of the library is permitted. But if further libraries are reloaded as dependencies in the library itself or a script element is used, this leads to an error since the value for nonce is not set there. The second case relates to parser-inserted script elements. A simple example of a parser-inserted element looks like this:
var scriptPath = “https://othercdn.not-example.net/dependency.js” document.write(“<script src=” + scriptPath + “></script>”);
With the expression
strict-dynamic, CSP Level 3 offers a solution for this problem and simplifies the use of external libraries. Using
strict-dynamic in conjunction with
nonce results in two changes, or effects:
script-src, as well as the use of
unsafe-inline, are rejected.
For practical purposes, this offers two benefits. The first effect permits a backwards-compatible rollout of
strict-dynamic. The policy
Content-Security-Policy: “unsafe-inline” https: “nonce-abcdefg” “strict-dynamic”
"unsafe-inline" https: in browsers that support CSP Level 1. The
https: "nonce-abcdefg" part applies in the case of Level 2 support and
"nonce-abcdefg" "strict-dynamic" applies in browsers that have implemented CSP Level 3. The second effect entrusts the integrated script with the integration of its own dependencies without the need to list them specifically in the whitelist.
One worthwhile presentation on CSP bypasses and the introduction of
strict-dynamic is the talk by Lukas Weichselbaum and Michele Spagnuolo, both information security engineers at Google, entitled Breaking Bad CSP! at this year“s Area41 2016. The slides from the talk are also available.
Content-Security-Policy header instructs the web browser to enforce the defined directives. This can, and experience shows that it does, lead to problems with the introduction of CSP or in the development phase of web applications. Therefore, a second CSP header called
Content-Security-Policy-Report-Only reports infringements of the directive without blocking them. The web browser sends a report to the URL defined in the directive
report-uri or, in future,
The report contains the following elements:
document-uri– the page where the infringement occurred
referrer– the referrer of the page
blocked-uri– the base address of the blocked URI
violated_directive– the specific directive that was infringed
original-policy– the complete CSP
These reports can be evaluated in respect to overly strict directives, infringements of the directive caused by programming errors or flaws in the web application, as well as potential XSS attacks. The IT security researcher Scott Helme offers a free service for collating and evaluating CSP reports at the website report-uri.io. This website is suitable for a first attempt with CSP without the need to build a reporting infrastructure, or with publicly accessible websites that do not contain sensitive data. For sensitive websites, the report service should be operated by a system under your own control.
Our experts will get in contact with you!
Our experts will get in contact with you!
Further articles available here