Definition
DOM clobbering is a vulnerability that occurs when HTML attributes (such as id
, name
) accidentally override undefined global JavaScript variables or default object properties
This can lead to unexpected behavior or security issues: DOM clobbering can be considered a type of XSS (cross site scripting) attack
<a id="globalConfig" href="hacked.js" />
<script>
const script = document.createElement('script');
let config = window.globalConfig || {href: 'script.js'};
script.src = config.href;
document.body.appendChild(script);
console.log(script.src); // hacked.js
</script>
This can happen in legacy JavaScript codebases, where global variables were stored directly in global object, by mistake or by design (using window
, document
, history
, localStorage
) but even in modern application
DOM clobbering can leverage this particular browser behavior to mess with object values.
Similarly to prototype pollution, it can lead to:
- RCE (Remote Code Execution) (with prototype pollution on Node.js)
- client-side CSRF (cross-site request forgery)
- privilege escalation issues
Code fragments called script gadget can interact to injected HTML markup and transform it into executable code
Combine pairs of HTML tags or browser specific markups and attributes, is it possible to modify:
- deep object properties
- nested window proxies
- loops
A widespread issue
DOM clobbering vulnerabilities have been found in Gmail and Google Analytics
The problem is growing over time (!)
When looking at the evolution of DOM Clobbering attack markups, we observe a consistent complexity growth:
- starting from a single HTML element that can overwrite a variable,
- evolving with pairs of HTML tags that clobber properties of objects (2013-15)
- then advancing into a wide variety of browser-specific combinations of different HTML tags and attributes that can not only overwrite variables, but also native DOM objects (2015-18)
- even nested object properties, and loop elements (2018-22)
Types of DOM clobbering
Named Access Window (R1)
These groups of markups leverage a single HTML element whose id
or name
is set to a target variable x
, clobbering window.x
- as a final result, both
window.x
andx
(which is interpreted as global x belonging to window) are clobbered
==Any custom HTML tag, even invalid tags, can be used to clobber a target variable in the window
object in all browsers==
<body>
<customTag id="x" test="true"></eruihiudfh>
</body>
<script defer>
console.log( window.x.getAttribute('test') ); // true
</script>
DOM Tree Accessors (R2)
The markups of this group can shadow document
object properties because browsers comply with the DOM Tree Accessors rule, which instructs browsers how to retrieve properties of the document object (e.g., DOM elements)
- Similarly to the previous group, these markups use a single named HTML element (e.g., object, or embed) to clobber a property
x
of the document.
Form parent-child relationships (R3)
These markups clobber properties X.y
where X
can be any of x
, window.x
, and document.x
- First, they exploit either the rules R1 or R2 to clobber the base object
X
- Then, they use the Form Element rule (R3) to clobber property
y
of objectX
, i.e., the form elements’ parent-child relationships where the browser creates a property of the second element for the first element’s accessor variable
DOM Clobbering code that rely on this technique include a form tag and a child (e.g., an input)
Nested Window Proxies (R4)
These markups use the Iframe srcdoc
rule (R4) to create nested window proxies that are named with x
and y
, respectively.
- Similarly to the previous group of markups, it uses the rule R1 or R2 to clobber the base object
- Then, the stacked iframes enable attackers to exploit frame navigation features to clobber object properties like
x.y
HTMLCollection (R5)
The last group of markups rely on a different rule known as HTMLCollection
(R5)
- when two or more elements have the same
id
in theDOM
tree, browsers create an array-like object calledHTMLCollection
, which contains all elements with the sameid
- Elements inside
HTMLCollections
can be accessed by their index in the collection and theirid
andname
, enabling attackers to abuse R5 to clobber arrays and loop elements. as well as object properties likex.x
andx.y
- in Chrome and Firefox, for
object
andform
tags, theHTMLCollection
is created even with two identicalname
values
Similarly to the previous techniques, rules R1-2 can be combined with R5 to clobber nested object properties like window.x.y.
Even native browsers' DOM APIs can be clobbered (347 in total)
Mitigation techniques
HTML sanitizers
- HTML sanitizers tailored to protect against DOM clobbering (e.g., DOMPurify, HTML Janitor), or implementing CSP (Content Security Policy)
- Unfortunately, even these libraries are vulnerable to DOM clobbering, indicating that they don’t offer a complete protection
- to prevent XSS attacks, the
script-src
directive can be used to limit the value of scripts sources to a set of trusted domains - CSP cannot guarantee protection against DOM clobbering that affects properties other than
src
Object.freeze()
- this powerful method prevents the object to be overwritten by named DOM elements
- detecting all the objects that can be frozen is a non trivial and error-prone task
- native properties cannot be frozen
Other techniques:
- do not use global variables (without
let
orconst
) - do not rely on
window
ordocument
object in sensitive operations - double check variables type with
instanceof
andtypeof
operators
References
Project SLR: