Exploiting DOM clobbering to enable XSS
Description
This lab contains a DOM-clobbering vulnerability. The comment functionality allows “safe” HTML.
Reproduction and proof of concept
Analysis:
The site uses the DOMPurify
filter in an attempt to reduce DOM-based vulnerabilities.DOMPurify
allows for the use of the cid:
protocol, which does not URL-encode double-quotes. This means an encoded double-quote can be injected that will be decoded at runtime. As a result, an injection can cause the defaultAvatar
variable to be assigned the clobbered property {avatar: ‘cid:"onerror=alert(1)//’}
the next time the page is loaded.
The defaultAvatar
object is implemented using this dangerous pattern containing the logical OR operator in conjunction with a global variable. This makes it vulnerable to DOM clobbering.
This object can be clobbered using anchor tags. Creating two anchors with the same ID causes them to be grouped in a DOM collection. The name attribute in the second anchor contains the value avatar
, which will clobber the avatar property with the contents of the href attribute.
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:"onerror=alert(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.
The page for a specific blog post imports the JavaScript file loadCommentsWithDomPurify.js
, which contains the following code:
let defaultAvatar = window.defaultAvatar || {avatar: '/resources/images/avatarDefault.svg'}
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()
.
Exploitability
To solve this lab, an attacker will need to construct an HTML injection that clobbers a variable and uses XSS to call the alert()
function.