Content-Security-Policy: misconfigurations and bypasses


The Content Security Policy (CSP) is a security mechanism web applications can use to reduce the risk of attacks based on XSS, code injection or clickjacking. Using different directives it is possible to lock down web applications by implementing a whitelist of trusted sources from which web resources like JavaScript may be loaded. Currently the CSP version 2 is supported by Firefox, Google Chrome, and Opera, whereas other browsers provide limited support or no support at all (Internet Explorer)[4].

The CSP has two modes of operation [7]: enforcing and report-only. The first one can be used to block and report attacks whereas the second one is used only to report abuses to a specific reporting server. In this blog post, we will focus only on the enforcing mode.

The policy, in order to work, has to be included in each HTTP response as a header (“Content-Security-Policy:”). The browser will then parse the CSP and check if every object loaded in the page adheres to the given policy. To specify these rules, the CSP provides different directives [5]:

  • script-src: defines valid sources of JavaScript
  • object-src: defines valid sources of plugins, like <objects>
  • img-src: defines valid sources of images
  • style-src: defines valid source of stylesheets
  • report-uri: the browser will POST a report to this URI in case of policy violation

Each of these directives must have a value assigned, which is usually a list of websites allowed to load resources from. The default behavior of directives if omitted, is to allow everything (“*”) without restrictions [9]. A basic example of a valid CSP is shown below:

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

The directive “default-src” is set to ‘self’, which means same origin. All resources without a directive set are allowed to be loaded only from the same origin, in this case “”. Setting the “default-src” directive can be a good start to deploy your CSP as it provides a basic level of protection. “script-src” is used to allow all JavaScripts to be loaded from the domain “”, via HTTP (https:// should be explicitly specified) without allowing subdomains. These could be specified directly (e.g. or using the “*” wildcard (*

Misconfigurations and Bypasses

Even though it is possible to have a good level of control over the policy, errors in the definition of directives may lead to unexpected consequences. Misconfiguration or ambiguities can render the policy less efficient or easy to bypass. In addition, the functionality of the application could also be broken. The following example illustrates what can happen if “default-src” is omitted:

Content-Security-Policy: script-src

Now, all the scripts with source “” are allowed. But what about the other objects like stylesheets or flash applets? The policy above can be bypassed for example using this payload, which triggers an alert box using a Flash object[7]:

">'><object type="application/x-shockwave-flash" 
<param name="AllowScriptAccess" value="always"></object>

One other common mistake is the inclusion of the dangerous “unsafe-inline” or “unsafe-eval” directives. These allow the execution of potentially malicious JavaScript directly via “<script>” tags or eval():

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

This policy defines the default source as “self” and allows the execution of script from “” but, at the same time, it allows the execution of inline scripts. This means that the policy can be bypassed with the following payload [7]:


The browser will then parse the JavaScript and execute the injected malicious content.

Besides these trivial misconfigurations shown above, there are some other tricks used to bypass CSP that are less common and known. These make use, for example, of JSONP (JSON with padding) or open redirects. Let’s take a look at JSONP bypasses.

If the CSP defines a whitelisted JSONP endpoint, it is possible to take advantage of the callback parameter to bypass the CSP. Assuming that the policy is defined as follows:

Content-Security-Policy: script-src 'self';

The domain hosts a JSONP endpoint, which can be called with the following URL:{functionName}

Now, what happens if the {functionName} parameter contains a valid JavaScript code which could be potentially executed? The following payload represents a valid bypass [7]:

">'><script src=";u">

The JSONP endpoint will then parse the callback parameter, generating the following response:

Alert(1); u({……})

The JavaScript before the semicolon, alert(1), will be executed by the client when processing the response received.

URLs with open redirects could also pose problems if whitelisted in the CSP. Imagine if the policy is set to be very restrictive, allowing only one specific file and domain in its “script-src” directive:

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

At first sight, this policy seems to be very restrictive: only the myfile.js can be loaded along with all the scripts originating from “” which is a site we trust. However, performs open redirects through a parameter in the URL. This could be a possible option to bypass the policy [7]:

">'><script src="">

Why is it possible to bypass the CSP using this payload? The CSP does not check the landing page after a redirect occurs and, as the source of the script tag “” is whitelisted, no policy violation will be triggered.

These are only a small subset of possible CSP bypasses. If you are interested, many of them can be found at [6] or [7].

The “nonce” directive

Besides the whitelist mechanism using URLs, in the CSP2 there are other techniques that can be used to block code injection attacks. One of these is represented for example by “nonces”.

Nonces are randomly generated numbers that should be defined in the CSP and included only inside <script> or <style> tags to identify resources and provide a mapping between the policy and the client’s browser. An attacker injecting a payload containing a script tag has no knowledge of the nonce previously exchanged between the client and the server, resulting in the CSP detecting this and throwing a policy violation. A possible configuration of a CSP with nonces could be:

Content-Security-Policy: script-src 'nonce-eED8tYJI79FHlBgg12'

The value of the nonce (which should be random, unpredictable, generated with every response, and at least 128 bits long [10]) is “eED8tYJI79FHlBgg12”.

This value should be then passed to each script tag included in our application’s pages:

<script src="http://source/script.js" nonce="eED8tYJI79FHlBgg12">

The browser will then parse the CSP, check if the scripts included have a matching value and block those that do not include any valid nonce. This technique works great against stored XSS, as the attacker cannot include valid nonces at injection time. Another advantage is that there is no need to maintain whitelists of allowed URLs, as the nonce acts as an access token for the <script> tag and not necessarily for the source of the script. It is also possible to use hashes in order to identify the content of each <script> element inside the page, more information about this feature can be found at [8].


We have seen that the CSP is a very useful tool web developers can use to have better control on the loaded resources. The different directives provide flexibility to allow or deny potentially dangerous web resources inside web pages. However, it is also easy to make errors if too many URLs are whitelisted (e.g. hidden JSONP endpoints). Here at Compass we encourage the use of the CSP as an additional barrier against web threats. Nonetheless, I would like to stress that the first protection against code injection should always be provided by a solid input/output validation, which can help also against other common attacks like SQL injections.

If you would like to get more information about how web applications should be protected, or you want to deepen your web security knowledge we provide different trainings:

We are also offering trainings in other areas of IT Security. You can check the different topics here:

Sources & References


APT Detection & Network Analysis

Until recently, the majority of organizations believed that they do not have to worry about targeted attacks, because they consider themselves to be “flying under the radar”. The common belief has been: “We are too small, only big organizations like financial service providers, military industry, energy suppliers and government institutions are affected”.

However, this assumption has been proven wrong since at least the detection of Operation ShadyRAT[0], DarkHotel[1] or the recent “RUAG Cyber Espionage Case”[2]. The analysis of the Command & Control (C&C) servers of ShadyRAT revealed that a large-scale operation was run from 2006 to 2011. During this operation 71 organizations (private and public) were targeted and spied on. It is assumed that these so-called Advanced Persistent Threats (APT) will even increase in the near future.

We at Compass Security are often asked to help finding malicious actions or traffic inside corporate networks.

The infection, in most cases, is a mix of social engineering methods (for example spear phishing) and the exploitation of vulnerabilities. This actually varies from case to case. Often we observe in proxy logs, that employees were lured into visiting some phishing sites which are designed to look exactly like the corporation’s Outlook Web Access (OWA) or similar applications/services as being used by the targeted company.

Typically, this is not something you can prevent exclusively with technical measures – user awareness is the key here! Nevertheless, we are often called to investigate when there still is some malware activity in the network. APT traffic detection can then be achieved with the correlation of DNS, mail, proxy, and firewall logs.

Network Analysis & APT Detection

To analyze a network, Compass Analysts first have to know the network’s topology to get an idea of how malware (or a human attacker) might communicate with external servers. Almost every attacker is going to exfiltrate data at some point in time. This is the nature of corporate/industrial espionage. Further, it is important to find out whether the attacker gained access to other clients or servers in the network.

For the analysis, log files are crucial. Many companies are already collecting logs on central servers [3], which speeds up the investigation process, since administrators don’t have to collect the logs from many different sources (which sometimes takes weeks), and off-site logs are more difficult to clear by attackers.

To analyze logs and sometimes traffic dumps, we use different tools like:

ELK offers many advantages when it comes to clustering and configuration, but it doesn’t offer many pre-configured log parser rules. If you are lucky, you can find some for your infrastructure on GrokBase[4]. Otherwise there are plenty of tools helping you to build them on your own, such as e.g. Grok Debugger[5].

However, when analysis has to be kick-started fast, and you do not have time to configure large rulesets – Splunk comes with a wide range of pre-configured parsers.

After we gathered all logs (and in some cases traffic dumps), we feed them into Splunk/ELK/Moloch for indexing.

In a first step we try to clean the data set by removing noise. To achieve this, we identify known good traffic patterns and exclude them. Of course it is not always straight forward to distinguish between normal and suspicious traffic as some malware uses for example Google Docs for exfiltration. It takes some time to understand what the usual traffic in a network looks like. To clean the data set even more, we then look for connections to known malware domains.

There are plenty of lists available for this:

If we are lucky, the attacker used infrastructure provided by known malware service providers (individuals and organizations are selling special services just for the purpose of hosting malware infrastructure). But more sophisticated attacks will most likely use their own infrastructure.

After cleaning out the data sets, we look for anomalies in the logs (e.g. large amounts of requests, single requests, big DNS queries, etc.). Some malware is really noisy and as a consequence, easy to find. Some samples are connecting to their C&C servers in a high frequency. Other samples are requesting commands form C&C servers at regular time intervals (Friday 20:00 for example). Others connect just once.

Sometimes we also detect anomalies in the network infrastructure which are caused by employees, for example heavy usage of cloud services such as Google Drive or Dropbox. Often these constitute to so-called false positives.

To share our experiences and knowledge in this field, we created the Security Training: Network Analysis & APT.

This training will cover:

  • Configuration of evidence (What logs are needed?)
  • Static and Dynamic Log Analysis with Splunk
    • Splunk Basics and Advanced Usage
    • Detecting anomalies
    • Detecting malicious traffic
  • Attack & Detection Challenges

If you are interested please visit our “Security Trainings” section to get more information: or get in touch if you have questions.

The next upcoming training is on 22. and 23. September 2016 in Jona, click here to register.

Sources & References:
[0] Operation Shady RAT, McAfee,
[1] The Darkhotel APT, Kaspersky Lab Research,
[2] Technical Report about the Malware used in the Cyberespionage against RUAG, MELANI/GovCERT,
[3] “Challenges in Log-Management”, Compass Security Blog,
[4] GrokBase,
[5] Grok Debugger,
[x.0] APT Network Analysis with Splunk, Compass Security, Lukas Reschke,
[x.1] Whitepaper: Using Splunk To Detect DNS Tunneling, Steve Jaworski,