postMessage abuse
When it applies
The target sends or receives postMessage between windows/iframes (SSO, payment widgets, chat,
embeds). A receiver that doesn't validate the sender's origin will act on a message from your
page.
Why it works
postMessage is cross-origin by design; safety depends entirely on the receiver checking
event.origin and the sender setting a specific targetOrigin. Miss the origin check and any site
can drive the handler; use targetOrigin="*" and any embedder can read the message. Then it's just
a matter of what the handler does with event.data — often innerHTML, eval, location, or a
relayed token.
Method
- Find listeners: grep the JS for
addEventListener("message"/onmessage; note the sink each handler feeds (innerHTML,eval,document.write,location, anotherpostMessage). - Check the origin guard: no check, or a weak one —
origin.indexOf("trusted")>-1,origin.endsWith("site.com")(matchessite.com.evil), a loose regex — is exploitable. - Drive the sink (XSS): host a page that
open()s or<iframe>s the target andpostMessage()s a payload the handler writes to a DOM sink → script execution. - Steal data (leak): if the target sends messages with
targetOrigin="*"(tokens, PII), embed it and read them in yourmessagelistener. - Bypass a bad check: register your attacker origin to satisfy the substring/regex flaw
(
trusted.attacker.com,attackertrusted.com).
Gotchas
event.origin(the sender) is the thing to validate — notevent.sourceand not the URL bar.- Sandboxed iframes and
X-Frame-Options/CSPframe-ancestorsmay stop framing — use a popup (window.open) instead. - Some handlers require a specific
datashape/handshake — replay the legit message first, then mutate.
Verify success
A message from your attacker page reaches a dangerous sink (script executes / navigation happens) or you read a secret the target broadcast — reproducible from an external origin.
References
PortSwigger DOM-based / postMessage; MDN Window.postMessage security notes.