diff --git a/src/pentesting-web/postmessage-vulnerabilities/README.md b/src/pentesting-web/postmessage-vulnerabilities/README.md index 82aa639e12e..76651cbae63 100644 --- a/src/pentesting-web/postmessage-vulnerabilities/README.md +++ b/src/pentesting-web/postmessage-vulnerabilities/README.md @@ -247,6 +247,43 @@ For **more information**: - Link to page about [**XSS**](../xss-cross-site-scripting/index.html) - Link to page about [**client side prototype pollution to XSS**](../deserialization/nodejs-proto-prototype-pollution/index.html#client-side-prototype-pollution-to-xss) +### Trusted-origin allowlist isn't a boundary + +A strict `event.origin` check only works if the **trusted origin cannot run attacker JS**. When privileged pages embed third-party iframes and assume `event.origin === "https://partner.com"` is safe, any XSS in `partner.com` becomes a bridge into the parent: + +```javascript +// 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 +}) +``` + +Attack pattern observed in the wild: + +1. **Exploit XSS in the partner iframe** and drop a relay gadget so any `postMessage` becomes code exec inside the trusted origin: + +```html + +``` + +2. **From the attacker page**, send JS to the compromised iframe that forwards an allowed message type back to the parent. The message originates from `partner.com`, passes the allowlist, and carries HTML that is inserted unsafely: + +```javascript +postMessage({ + cmd: `top.frames[1].postMessage('Partner.learnMore||b|c', '*')` +}, "*") +``` + +3. The parent injects the attacker HTML, giving **JS execution in the parent origin** (e.g., `facebook.com`), which can then be used to steal OAuth codes or pivot to full account takeover flows. + +Key takeaways: + +- **Partner origin isn't a boundary**: any XSS in a "trusted" partner lets attackers send allowed messages that bypass `event.origin` checks. +- Handlers that **render partner-controlled payloads** (e.g., `innerHTML` on specific message types) make partner compromise a same-origin DOM XSS. +- A wide **message surface** (many types, no structure validation) gives more gadgets for pivoting once a partner iframe is compromised. + ### Predicting **`Math.random()`** callback tokens in postMessage bridges When message validation uses a “shared secret” generated with `Math.random()` (e.g., `guid() { return "f" + (Math.random() * (1<<30)).toString(16).replace(".", "") }`) and the same helper also names plugin iframes, you can recover PRNG outputs and forge trusted messages: @@ -277,6 +314,7 @@ iframe.location = fbMsg // sends postMessage from facebook.com with forged callb - [https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd](https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd) - [Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO](https://ysamm.com/uncategorized/2026/01/16/leaking-fbevents-ato.html) - To practice: [https://github.com/yavolo/eventlistener-xss-recon](https://github.com/yavolo/eventlistener-xss-recon) +- [Self XSS Facebook Payments](https://ysamm.com/uncategorized/2026/01/15/self-xss-facebook-payments.html) - [Facebook JavaScript SDK Math.random callback prediction → DOM XSS writeup](https://ysamm.com/uncategorized/2026/01/17/math-random-facebook-sdk.html) - [V8 Math.random() state recovery (Z3 predictor)](https://github.com/PwnFunction/v8-randomness-predictor)