Full Report
The author of this post was reviewing a target that had an interactive playground for developers to write and evaulate Javascript to interact with a developer API. This is a great attack surface to target! Sometimes, the vulnerability is the attack surface. The application attempts to sandbox the users JavaScript execution by creating a separate iframe and running the code in there. However, the iframe didn't contain the sandbox attribute, depsite being in a dive and having a name that contained sandbox in it. This means that the iframe is considered same origin and can access content within the parent page. The iframe creation sets the src via data:text.... Normally, this would mean it has the null origin. Luckily for the author, the page calls document.open() and document.write() on the iframes document before the URI loads! This means that the iframe's origin is from the parent. In practice, this means that any code injected into the textarea is evaulated on the full origin of the target site. This creates DOM XSS but they needed a remote way to exploit it. How do we get a user to add this payload? The author has many posts are weaponizing drag in drop across windows. When a user starts dragging an element on Page A, which then redirects to page B, the drag action persists across windows. To exploit this, an attacker can host a page with an attractive draggable image, set the drag data to be an XSS payload, redirect to the victim page and when the user releases the drag, it drops right into the code editor. This works on Firefox and Safari. On Chrome, it requires a popup instead of a redirect. Even with the drag and drop exploit, the victim still needs to click Evalulate. Luckily for them, there's a postMessage handler that doesn't check the origin. So, any cross-origin window is able to call Evalulate on the editor. With this, they can achieve full XSS via some user interaction. The chain is a drag-n-drop switcheroo with an XSS payload onto the parent page that is triggered by a postMessage. Full XSS wasn't enough; they wanted to get an account takeover. The website used OAuth for logging in. They prevented the OAuth callback from working server-side by using a cookie bomb to trigger a 431 error. Now, the auth code is UNUSED within the URL but the code wasn't used. Using this authorization code leads to a complete account takeover. This is a crazy chain of bugs! It does require a drag-n-drop so the triager on the bug bounty program says that it requires too much interaction. Still, the techniques used are pretty awesome and I loved about client-side security from this post. Great write up!
Analysis Summary
# Vulnerability: Multi-Stage DOM XSS and OAuth Account Takeover via Drag-and-Drop Chain
## CVE Details
- **CVE ID**: Not Assigned (Discovered via Bug Bounty program)
- **CVSS Score**: 8.3 (High) - *Calculated based on High Confidentiality/Integrity impact with Required User Interaction*
- **CWE**: CWE-79 (Cross-site Scripting), CWE-1021 (Improper Restriction of Rendered UI Layers), CWE-444 (Inconsistent Interpretation of HTTP Requests)
## Affected Systems
- **Products**: Web applications featuring interactive JavaScript "Playground" or "Sandbox" editors for API testing.
- **Versions**: Platform version at the time of the research (unspecified).
- **Configurations**:
- Use of iframes without the `sandbox` attribute.
- Iframes initialized via `document.open()`/`document.write()`, inheriting the parent origin.
- Broken `postMessage` handlers lacking origin validation.
- OAuth implementation vulnerable to Authorization Code reuse or leakage.
## Vulnerability Description
The vulnerability stems from a failure to isolate user-supplied JavaScript within a developer playground. While the application attempted to use an iframe for sandboxing, the absence of the `sandbox` attribute and the method of document initialization (`document.write`) caused the iframe to maintain the same origin as the parent page.
This allowed any code within the iframe to access the parent's DOM. Furthermore, a secondary flaw in the `postMessage` event listener allowed any cross-origin site to trigger the "Evaluate" function of the script editor. Finally, the OAuth flow was vulnerable to an "unused code" flaw triggered by a "Cookie Bomb" (HTTP 431 Request Header Fields Too Large), allowing an attacker to intercept and use a valid authorization code.
## Exploitation
- **Status**: PoC available (Demonstrated by author)
- **Complexity**: High (Requires multi-stage orchestration and specific user interaction)
- **Attack Vector**: Network (Web-based via User Interaction)
### Exploitation Chain:
1. **Drag-and-Drop Switcheroo**: The attacker hosts a page with a draggable element containing an XSS payload. When the user starts the drag, the page redirects to the target site.
2. **Payload Injection**: The user completes the "Drop" into the playground text area.
3. **Trigger**: The attacker’s page uses `window.postMessage` to trigger the "Evaluate" button on the target site.
4. **Account Takeover**: To capture an OAuth code, the attacker "bombs" the victim's cookies to cause a server-side 431 error. This prevents the code from being consumed by the legitimate server, allowing the attacker to steal the valid code via XSS and reuse it.
## Impact
- **Confidentiality**: High (Full access to session data, API keys, and OAuth codes)
- **Integrity**: High (Ability to execute arbitrary actions on behalf of the user)
- **Availability**: Medium (Cookie bombing can temporarily deny service to the user)
## Remediation
### Patches
- **Iframe Hardening**: Implement the `sandbox` attribute on all user-content iframes (e.g., `<iframe sandbox="allow-scripts">`).
- **Origin Validation**: Strict validation of `event.origin` in all `postMessage` handlers.
- **OAuth Security**: Ensure Authorization Codes are strictly tied to a single-use policy and validated against the original redirect URI.
### Workarounds
- **Content Security Policy (CSP)**: Implement a strict CSP that restricts `frame-src` and prevents the execution of unsafe inline scripts.
- **Input Sanitization**: Sanitize data received via Drag-and-Drop events before inserting it into the DOM.
## Detection
- **Indicators of Compromise**:
- Unexpected `postMessage` calls from unauthorized origins.
- Excessive cookie growth or 431 Request Header Fields Too Large errors in server logs.
- Unusually large or malformed data strings being "dropped" into UI elements.
- **Detection Tools**:
- Browser developer tools to monitor `postMessage` traffic.
- DAST scanners configured to test for iframe origin inheritance.
## References
- [https://example[.]com/post-on-weaponizing-drag-and-drop] (Defanged Reference)
- [https://developer[.]mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox] (Iframe Sandbox Documentation)
- [https://portswigger[.]net/web-security/cross-site-scripting/dom-vulnerabilities] (DOM XSS Research)