November 20, 2008

Bubbling, foreign events and Firefox

Intro

One of the major differences of the back then two important browsers was how they handled events. Microsoft worked with the bubbling phase - meaning the event first passes the parent elements and then runs down to the target element. Netscape did it the exact other way - and had the event first hit on the target element and then traverse the whole DOM upwards hitting on the parent nodes - capturing. This caused developers in the early days a lot of trouble and the W3C finally specified an approach where both kind of works and can be used at free will.

The following code illustrates how it works - watch the order the alerts will pop up and tell what element is affected.

<html>
<body>
<ul>
<li onchange="alert(this)">
<form onchange="alert(this)" action="#">
<select onchange="alert(this)">
<option>change me!</option>
<option>yes!</option>
</select>
</form>
</li>
</ul>
</body>
</html>

The interesting thing is that the most current Firefox versions still seem to carry a lot of the older code from back in the days when Mozilla was fresh and behaves extremely strange when coming to bubbling and foreign events

Some more code

Normally a LI element would not work together with an onselect event handler - which is good because if it would Firefox would kind of have to fire a select event as soon a list bullet is being clicked. But during the bubbling phase it actually does. Of course only in Firefox and no other of the tested browsers. The following example demonstrates that.

<html>
<body>
<ul>
<li onselect="alert(this)">
<form onselect="alert(this)" action="#">
<input type="text" onselect="alert(this)" value="select me!" />
</form>
</li>
</ul>

At least this doesn't work for all events - onerror and onload seem to be ignored and don't generate the above described effect. For an attacker that means events can be captured even if a filter would block the injection of matching elements - in case the injectable element can be placed as parent node of the element that handles the event and is meant to be hijacked.

Conclusion

That behavior could be described as a bug - and is not reproducible on any other browser than Firefox and other Gecko based software. Even more irritating is the fact that Firefox seems to have severe difficulties with parsing the page in the right order when bubbling. Let's have a look at the next example.

<html onclick="alert(this)">
<body onclick="alert(this)">
<div onclick="alert(this)"></div>
<div onclick="alert(this)">
<a href="#" onclick="alert(this)" id="test">foo</a>
</div>
</body>
</html>

On some machines the last alert Firefox produces says [object Window] - on others it says [object HTMLBodyElement and not the HTML object as any other browser would do. So as it seems the parser has difficulties parsing the DOM tree during the bubbling phase - which again opens a small attack window in certain scenarios.

The series of articles on events will be continued the next weeks so stay tuned for more.