Skip to content

Add insecure postMessage example in test22.html#32

Open
maekuss wants to merge 1 commit into
mainfrom
maekuss-patch-10
Open

Add insecure postMessage example in test22.html#32
maekuss wants to merge 1 commit into
mainfrom
maekuss-patch-10

Conversation

@maekuss

@maekuss maekuss commented Jun 16, 2026

Copy link
Copy Markdown
Owner

This HTML file demonstrates an insecure postMessage implementation that does not validate the origin of incoming messages, allowing for potential DOM injection attacks.

This HTML file demonstrates an insecure postMessage implementation that does not validate the origin of incoming messages, allowing for potential DOM injection attacks.

@hacktron-app-stg hacktron-app-stg Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file

Severity Count
HIGH 1

View full scan results

Comment thread test22.html

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HIGH DOM-based Cross-Site Scripting (XSS) via Insecure postMessage Listener

Vulnerable Behavior and Root-Cause Code Pattern

The file test22.html registers a global message listener using window.addEventListener('message', ...). Within this listener, the application fails to validate the sender's origin (event.origin). It then takes the payload event.data and directly assigns it to the innerHTML property of the output element (document.getElementById('output').innerHTML = incoming;). This direct assignment of unsanitized, untrusted cross-origin data to a dangerous DOM sink results in a DOM-based Cross-Site Scripting (XSS) vulnerability.

Preconditions and Assumptions

  1. The vulnerable page (test22.html) is hosted on a web server and accessed by a victim user.
  2. The attacker is able to induce the victim to visit a malicious website or click on a link controlled by the attacker.

Attacker Model and Exploitation Path

  • Attacker Profile: An external, unauthenticated malicious web actor.
  • Reachability: The attacker can reach the victim's browser session by hosting a malicious webpage.
  • Exploitation Path:
    1. The victim visits the attacker's malicious website.
    2. The attacker's page opens the vulnerable test22.html page in a new window (using window.open) or embeds it in an iframe.
    3. The attacker's page uses postMessage to send a message containing a malicious payload (e.g., <img src=x onerror="alert(document.domain)">) to the opened/embedded window.
    4. The vulnerable page receives the message, bypasses origin validation (since none exists), and assigns the payload to innerHTML.
    5. The browser executes the injected JavaScript payload in the context of the vulnerable page's origin.

Security Impact

An attacker can execute arbitrary JavaScript in the context of the victim's session on the vulnerable origin. This allows the attacker to steal session tokens, access sensitive user data, perform actions on behalf of the user, or deface the web application.

Steps to Reproduce

An attacker can host the following HTML page to exploit the vulnerability:

<!DOCTYPE html>
<html>
<head>
  <title>Attacker Page</title>
</head>
<body>
  <script>
    // Open the vulnerable target window
    const targetWindow = window.open('http://target-domain/testerror/test22.html', 'target');

    // Wait for the target window to load and send the malicious payload
    setTimeout(() => {
      const payload = `<img src="invalid-image" onerror="alert('XSS Exploit! Document Domain: ' + document.domain)">`;
      targetWindow.postMessage(payload, '*');
    }, 1500);
  </script>
</body>
</html>
Fix with AI

Open in Cursor Open in Claude

A security vulnerability was found by Hacktron.

File: test22.html
Severity: high

Vulnerability: DOM-based Cross-Site Scripting (XSS) via Insecure postMessage Listener

Description:
### Vulnerable Behavior and Root-Cause Code Pattern
The file `test22.html` registers a global message listener using `window.addEventListener('message', ...)`. Within this listener, the application fails to validate the sender's origin (`event.origin`). It then takes the payload `event.data` and directly assigns it to the `innerHTML` property of the `output` element (`document.getElementById('output').innerHTML = incoming;`). This direct assignment of unsanitized, untrusted cross-origin data to a dangerous DOM sink results in a DOM-based Cross-Site Scripting (XSS) vulnerability.

### Preconditions and Assumptions
1. The vulnerable page (`test22.html`) is hosted on a web server and accessed by a victim user.
2. The attacker is able to induce the victim to visit a malicious website or click on a link controlled by the attacker.

### Attacker Model and Exploitation Path
- **Attacker Profile**: An external, unauthenticated malicious web actor.
- **Reachability**: The attacker can reach the victim's browser session by hosting a malicious webpage.
- **Exploitation Path**:
  1. The victim visits the attacker's malicious website.
  2. The attacker's page opens the vulnerable `test22.html` page in a new window (using `window.open`) or embeds it in an iframe.
  3. The attacker's page uses `postMessage` to send a message containing a malicious payload (e.g., `<img src=x onerror="alert(document.domain)">`) to the opened/embedded window.
  4. The vulnerable page receives the message, bypasses origin validation (since none exists), and assigns the payload to `innerHTML`.
  5. The browser executes the injected JavaScript payload in the context of the vulnerable page's origin.

### Security Impact
An attacker can execute arbitrary JavaScript in the context of the victim's session on the vulnerable origin. This allows the attacker to steal session tokens, access sensitive user data, perform actions on behalf of the user, or deface the web application.

Proof of Concept:
An attacker can host the following HTML page to exploit the vulnerability:

```html
<!DOCTYPE html>
<html>
<head>
  <title>Attacker Page</title>
</head>
<body>
  <script>
    // Open the vulnerable target window
    const targetWindow = window.open('http://target-domain/testerror/test22.html', 'target');

    // Wait for the target window to load and send the malicious payload
    setTimeout(() => {
      const payload = `<img src="invalid-image" onerror="alert('XSS Exploit! Document Domain: ' + document.domain)">`;
      targetWindow.postMessage(payload, '*');
    }, 1500);
  </script>
</body>
</html>
```

Affected Code:
- [test22.html:30](https://github.com/example/repo/blob/main/testerror/test22.html#L30): `window.addEventListener('message', (event) => {`
- [test22.html:35-36](https://github.com/example/repo/blob/main/testerror/test22.html#L35-L36): 
  ```javascript
  const incoming = typeof event.data === 'string' ? event.data : JSON.stringify(event.data);
  document.getElementById('output').innerHTML = incoming;
  ```

Acceptance criteria:
- Acceptance is defined by the **actual reported behavior**, not by tests passing.
- Reproduce the issue, or narrow the exact code path that produces it, *before* changing code. State what you confirmed.
- Fix the underlying cause. Mitigations that paper over the reported behavior do not count as a fix.
- Add a regression test that fails on the unpatched code and passes on the fix. If a regression test is genuinely impractical (e.g. race condition, infra-level issue), say so and explain why.
- Existing tests passing is **not** the bar. Do not declare done on tests-pass theatre.

Only change what is necessary to fix this vulnerability. Do not refactor adjacent code or modify unrelated files.

Triage: Reply !fp <reason> (false positive), !valid (confirmed), or !accepted_risk <reason>. Any other reply is saved as a triage note.
Reason is optional but improves future scans — e.g. !fp internal endpoint, not user-facing.

View finding in Hacktron

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant