December 07, 2008

There's XUL in it

Intro

XUL or XML User Interface Language is being used by Mozilla browsers and other related products to build the user interfaces. Most times the whole GUI consists of XUL - same for extensions and other components of the browsers, mail clients and other tools. It's fun and easy to write XUL code because as the name already indicates it's XML and writing XUL is not really that different from writing HTML and CSS.

Code

Firefox surprisingly allows to use a subset of XUL elements in regular HTML pages - at least as long as they are being delivered as XML which happens pretty often. And probably will happen even more often in the future. The last article touched XML namespaces and how they can be misused to circumvent blacklist-based filters. The problem was that the attacker would have been able to influence the contents of the header area of the attacked web page. With XUL namespaces this is no longer the case - as the following code demonstrates.

<xul:button
   onclick="alert(1)"
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   label="Click me baby one more time"
/>

Conclusion

The example showed a way to execute script as reaction on a click. Using the XUL image element we can of course also create elements that execute the wanted code without any user generated events necessary to happen.

<xul:image
   onerror="alert(2)"
   src="x"
   xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
/>

And of course we don't have to call the namespace xul - we can also call it x or something completely different. Important is just one fact - that the xmlns:name attribute points to the right URI.

<x:image
   src="x"
   onerror="alert(3)"
   xmlns:x="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
/>

It's questionable why these kinds of elements have to work for regular websites - and why the URI of the namespace attribute is so important. Placing the namespace file somewhere else and changing the URI renders the elements invisible - so it's mandatory that the attribute points to http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul. It of course doesn't matter if the Mozilla server is available or not - the code works anyway.

So basically the above listed examples demonstrate just another way to easily circumvent blacklist-based input filters. The code of course exclusively works with software using the Gecko rendering engine - such as Firefox 3.0.4.