# Iframes u XSS, CSP i SOP {{#include ../../banners/hacktricks-training.md}} ## Iframes u XSS Postoje 3 načina da se označi sadržaj stranice unutar iframe-a: - Putem `src` koji označava URL (URL može biti različitog porekla ili istog porekla) - Putem `src` koji označava sadržaj koristeći `data:` protokol - Putem `srcdoc` koji označava sadržaj **Pristupanje roditeljskim i dečijim varijablama** ```html ``` ```html ``` Ako pristupite prethodnom html-u putem http servera (kao što je `python3 -m http.server`), primetićete da će svi skripti biti izvršeni (pošto ne postoji CSP koji to sprečava). **roditelj neće moći da pristupi `secret` varijabli unutar bilo kog iframe-a** i **samo iframe-ovi if2 i if3 (koji se smatraju istim sajtom) mogu pristupiti tajni** u originalnom prozoru.\ Obratite pažnju kako se if4 smatra da ima `null` poreklo. ### Iframes sa CSP > [!TIP] > Molimo vas, obratite pažnju kako u sledećim zaobilaženjima odgovor na iframed stranicu ne sadrži nijedan CSP header koji sprečava izvršavanje JS-a. `self` vrednost `script-src` neće dozvoliti izvršavanje JS koda koristeći `data:` protokol ili `srcdoc` atribut.\ Međutim, čak i `none` vrednost CSP-a će dozvoliti izvršavanje iframe-ova koji stavljaju URL (potpun ili samo putanju) u `src` atribut.\ Stoga je moguće zaobići CSP stranice sa: ```html ``` Napomena kako **prethodni CSP dozvoljava samo izvršavanje inline skripte**.\ Međutim, **samo `if1` i `if2` skripte će biti izvršene, ali samo `if1` će moći da pristupi roditeljskom tajnom**. ![](<../../images/image (372).png>) Stoga, moguće je **obići CSP ako možete da otpremite JS datoteku na server i učitate je putem iframe-a čak i sa `script-src 'none'`**. Ovo se **potencijalno može uraditi i zloupotrebom same-site JSONP krajnje tačke**. Možete testirati ovo sa sledećim scenarijom gde je kolačić ukraden čak i sa `script-src 'none'`. Samo pokrenite aplikaciju i pristupite joj putem vašeg pregledača: ```python import flask from flask import Flask app = Flask(__name__) @app.route("/") def index(): resp = flask.Response('') resp.headers['Content-Security-Policy'] = "script-src 'self'" resp.headers['Set-Cookie'] = 'secret=THISISMYSECRET' return resp @app.route("/cookie_s.html") def cookie_s(): return "" if __name__ == "__main__": app.run() ``` #### Nove (2023-2025) CSP bypass tehnike sa iframovima Istraživačka zajednica nastavlja da otkriva kreativne načine zloupotrebe iframova kako bi prevazišla restriktivne politike. Ispod možete pronaći najznačajnije tehnike objavljene tokom poslednjih nekoliko godina: * **Dangling-markup / named-iframe data-exfiltration (PortSwigger 2023)** – Kada aplikacija reflektuje HTML, ali jaka CSP blokira izvršavanje skripti, i dalje možete iscuriti osetljive tokene injektovanjem *dangling* ` ``` ### Iframe sandbox Sadržaj unutar iframe-a može biti podvrgnut dodatnim ograničenjima korišćenjem `sandbox` atributa. Po defaultu, ovaj atribut nije primenjen, što znači da nema ograničenja. Kada se koristi, `sandbox` atribut nameće nekoliko ograničenja: - Sadržaj se tretira kao da potiče iz jedinstvenog izvora. - Svaki pokušaj slanja formi je blokiran. - Izvršavanje skripti je zabranjeno. - Pristup određenim API-jima je onemogućen. - Sprečava interakciju linkova sa drugim kontekstima pretraživanja. - Korišćenje dodataka putem ``, ``, ``, ili sličnih oznaka je zabranjeno. - Navigacija vrhunskim kontekstom pretraživanja od strane samog sadržaja je sprečena. - Funkcije koje se automatski aktiviraju, poput reprodukcije videa ili automatskog fokusiranja kontrola formi, su blokirane. Tip: Moderni pretraživači podržavaju granularne oznake kao što su `allow-scripts`, `allow-same-origin`, `allow-top-navigation-by-user-activation`, `allow-downloads-without-user-activation`, itd. Kombinujte ih da biste omogućili samo minimalne mogućnosti potrebne ugrađenoj aplikaciji. Vrednost atributa može biti ostavljena prazna (`sandbox=""`) da bi se primenila sva prethodno navedena ograničenja. Alternativno, može se postaviti na listu specifičnih vrednosti razdvojenih razmakom koje izuzimaju iframe od određenih ograničenja. ```html ``` ### Credentialless iframes Kao što je objašnjeno u [ovom članku](https://blog.slonser.info/posts/make-self-xss-great-again/), `credentialless` oznaka u iframe-u se koristi za učitavanje stranice unutar iframe-a bez slanja kredencijala u zahtevu, dok se održava politika istog porekla (SOP) učitane stranice u iframe-u. Pošto je **Chrome 110 (februar 2023) ova funkcija omogućena po defaultu** i specifikacija se standardizuje među pretraživačima pod imenom *anonymous iframe*. MDN to opisuje kao: “mehanizam za učitavanje iframe-ova trećih strana u potpuno novoj, ephemernoj skladišnoj particiji tako da se nijeki kolačići, localStorage ili IndexedDB ne dele sa pravim poreklom”. Posledice za napadače i odbranu: * Skripte u različitim credentialless iframe-ovima **i dalje dele isto vrhunsko poreklo** i mogu slobodno da komuniciraju putem DOM-a, što čini multi-iframe self-XSS napade izvodljivim (vidi PoC ispod). * Pošto je mreža **bez kredencijala**, svaki zahtev unutar iframe-a se efektivno ponaša kao neautentifikovana sesija – CSRF zaštićene tačke obično ne uspevaju, ali javne stranice koje se mogu otkriti putem DOM-a su i dalje u opsegu. * Iskočeni prozori koji se pokreću iz credentialless iframe-a dobijaju implicitni `rel="noopener"`, što prekida neke OAuth tokove. ```javascript // 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 ``` - Primer eksploatacije: Self-XSS + CSRF U ovom napadu, napadač priprema zlonamernu veb stranicu sa 2 iframe-a: - Iframe koji učitava stranicu žrtve sa `credentialless` flagom sa CSRF-om koji pokreće XSS (Zamislite Self-XSS u korisničkom imenu korisnika): ```html
``` - Drugi iframe koji zapravo ima korisnika prijavljenog (bez `credentialless` flag-a). Zatim, iz XSS-a je moguće pristupiti drugom iframe-u jer imaju isti SOP i ukrasti kolačić, na primer izvršavanjem: ```javascript alert(window.top[1].document.cookie); ``` ### fetchLater Attack Kao što je navedeno u [ovom članku](https://blog.slonser.info/posts/make-self-xss-great-again/), API `fetchLater` omogućava konfiguraciju zahteva koji će biti izvršen kasnije (nakon određenog vremena). Stoga, ovo se može zloupotrebiti da, na primer, prijavi žrtvu unutar napadačeve sesije (sa Self-XSS), postavi `fetchLater` zahtev (da promeni lozinku trenutnog korisnika, na primer) i odjavi se iz napadačeve sesije. Tada se žrtva prijavljuje u svoju sesiju i `fetchLater` zahtev će biti izvršen, menjajući lozinku žrtve na onu koju je postavio napadač. Na ovaj način, čak i ako URL žrtve ne može biti učitan u iframe (zbog CSP-a ili drugih ograničenja), napadač i dalje može izvršiti zahtev u sesiji žrtve. ```javascript var req = new Request("/change_rights",{method:"POST",body:JSON.stringify({username:"victim", rights: "admin"}),credentials:"include"}) const minute = 60000 let arr = [minute, minute * 60, minute * 60 * 24, ...] for (let timeout of arr) fetchLater(req,{activateAfter: timeout}) ``` ## Iframes u SOP Proverite sledeće stranice: {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-1.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/bypassing-sop-with-iframes-2.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/blocking-main-page-to-steal-postmessage.md {{#endref}} {{#ref}} ../postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md {{#endref}} ## Reference * [PortSwigger Research – Korišćenje otmice formi za zaobilaženje CSP (mart 2024)](https://portswigger.net/research/using-form-hijacking-to-bypass-csp) * [Chrome Developers – Iframe bez kredencijala: Lako umetnite iframe u COEP okruženja (feb 2023)](https://developer.chrome.com/blog/iframe-credentialless) {{#include ../../banners/hacktricks-training.md}}