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='javascript:alert(1)'//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.