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

    DOM Clobbering

    By Gareth Heyes (@hackvertor)

    Published 12 years 11 months ago • Last updated March 26, 2025 • ⏱️ 3 min read

    ← Back to articles

    The DOM is a mess. In an effort to support legacy quick short cuts such as "form.name" etc the browsers have created a Frankenstein monster. This is well known of course but I just wonder how far the rabbit hole goes. I'm gonna share what I discovered over the years.

    HTML Collections

    First up is my favourite "HTML Collections", when html elements are combined into groups they become a collection. You can actually force a collection by giving an element the same name. Such as:

    <input id=x><input id=x><script>alert(x)</script>

    On IE "x" alerts "Object HTML Collection". What's interesting is there are two ways of doing this, via name and via id, because it's an array like structure you can reference each element by the order they appear in the collection e.g. collection[0] is the first element. We can use this functionality to "clobber" variables into window to create some interesting stuff. An example of this:

    <a href="invalid:1" id=x name=y>test</a> <a href="invalid:2" id=x name=y>test</a> <script>alert(x.y[0])</script>

    What is especially odd is that a collection constructed like this can refer to itself forever, for example:

    <script> alert(x.y.x.y.x.y[0]); alert(x.x.x.x.x.x.x.x.x.y.x.y.x.y[0]); </script>

    When the elements become a collection this of course removes the normal properties/methods on the HTML element if it was being referenced by name.

    <a href=1 name=x>test</a> <a href=1 name=x>test</a> <script> alert(x.removeChild)//undefined alert(x.parentNode)//undefined </script>

    You can see how that could cause problems :)

    Variable assignments cause anchor href modifications

    This is a very old bug probably a few years old now, it was rediscovered by @gsnedders. On IE a global variable with the same name as an anchor element caused modification of that anchors href. For example

    <a href="123" id=x>test</a> <script> x=&apos;javascript:alert(1)&apos;//only in compat! </script>

    If you have an anchor named "x" and an assignment with the same name then even if it is fully encoded you can still inject XSS by modifying the anchor directly.

    Framebusters busted

    Lastly on my trip down memory lane I have another interesting bug that was again found many moons ago. You might be familiar with code similar to this:

    <script> if(top!=self){ top.location=self.location } </script>

    It's checking if the top most window is the same as the current window (usually to prevent a page being framed). If we can clobber a form before the check then we can fool the logic into thinking that self is a form and "self.location" is an attribute on that form like this:

    <form name=self location="javascript:alert(1)"></form> <script> if(top!=self){ top.location=self.location } </script>

    Which fires the alert! But there's more, since an attribute is decoded when it's accessed we can encode the colon of course but because on IE when the assignment occurs it's also decoded we can now double encode! Which means this is perfectly valid too:

    <form name=self location="javascript&#58;alert(1)"></form> <script> if(top!=self){ top.location=self.location } </script>

    In conclusion the DOM is a mess.

    ← Back to articles