The Google Caja team has put forward a fantastic document on JavaScript-based injection attacks. This is a fascinating subject and one that receives little attention (but will, undoubtedly, receive more in the upcoming months and years as JavaScript receives more attention).
In their document they detail an injection attack against a SQL database (an obvious example with parallels to existing database injections). However there is another class of problems that are particularly problematic: HTML injection, by browser extensions, allowing web-based content to access privileged code in the browser.
There’s a specific example from early last year where a vulnerability was discovered in Firebug, using this very attack vector. (This hasn’t been an issue in a long time – I’ve waited to post these details until the issue had long passed.)
The details:
The vulnerability noticed in a post on GNUCITIZEN related to the escaping of object property names in Firebug. For example, you could run the following code:
console.log({'<script>alert("bing!")</script>':'exploit'})
and it would pop up an alert.
Normally, this wouldn’t be a huge concern (nothing more than a bug) – but the script that was executed had all the privileges of the normal browser (for example, to be able to read and delete files).
I was notified about this issue at about 4:36pm (EST), read through the details, tried the exploit, and then set about creating a patch. At 5:32pm I fixed the particular exploit and had a patch ready. At that time I set about trying to find other instances where this exploit could also work.
How the exploit works
Firebug has some very-cool DOM creation code embedded in it. One of the fundamental differences between it and normal DOM creation code is that it creates a serialized string of HTML as output, instead of a series of DOM objects. This means that .innerHTML can be used to inject the HTML (which is blazingly fast).
The published exploit occurred in such a case where a string was being put into this DOM-serialization code, but was not having its HTML characters escaped (in reps.js):
OBJECTLINK( SPAN({class: "objectTitle"}, "$object|getTitle"), FOR("prop", "$object|propIterator", " $prop.name=", // The un-escaped variable SPAN({class: "objectPropValue"}, "$prop.value|cropString|escapeHTML") ) )
The fix was simple, just changing the line in question to the following:
" $prop.name|escapeHTML=",
It was at this point that I started to dig around the rest of the Firebug code base, looking for more escaping exploits. At this point Joe published Firebug 1.02 (at about 5:47pm) before I could get any of my patches to him. Looking through the changes that he made, he fixed the exact line that I mentioned before – solving the published exploit.
After some more reading I found another exploit relating to the first one. If you click the serialized version of the (exploited) object in Firebug, it would open up the DOM inspector pane, and execute the un-escaped code.
This second exploit was found in dom.js (which runs the DOM inspection pane):
TR({class: "memberRow $member.open $member.type\\Row", $hasChildren: "$member.hasChildren", level: "$member.level"}, TD({class: "memberLabelCell", style: "padding-left: $member.indent\\px"}, DIV({class: "memberLabel $member.type\\Label"}, "$member.name") // un-escaped variable ), TD({class: "memberValueCell"}, TAG("$member.tag", {object: "$member.value"}) ) );
That was another quick patch:
DIV({class: "memberLabel $member.type\\Label"}, "$member.name|escapeHTML")
I notified Joe at about 6:30pm (and pointed out other interesting bits of code) and he set out to see if he could find another set of exploits, as well. Before the evening was over, he was able to find one other loophole in the XMLHttpRequest spying code, and resolve it. It was at this point that he packaged up and distributed Firebug 1.03 at about 7pm, incorporating the three different escaping vulnerabilities that we were able to locate. Later on he provided a systemic fix to the whole escaping issue which has solved future injection problems.
I found the whole experience to be very exciting, and fun; getting a fix out was the top priority, and that was definitely achieved. However, knowing how and why these types of attacks can happen is important to JavaScript development, as a whole. I’m really glad that the Caja team is doing good work in getting the word out.
Gareth Heyes (February 1, 2008 at 7:30 am)
It sounds like you’re becoming interested in Javascript security :D
Come and join the fun on slackers:-
http://sla.ckers.org/forum/read.php?2,15812
We try to find unusual javascript in order to bypass XSS filters etc, we could do with some input from you undoubted knowledge
dre (February 1, 2008 at 10:05 am)
What is the best way to specify and verify that bugs such as these do not occur/re-ocurr? Can tests that assert this sort of behavior be built as unit tests? I ran all of the demos on the JCoverage website the other day and am trying to think of good ways of making this part of testing plans.
It’s obvious that you like JUnit, J3Unit, and Test::Simple/More (as do most developer-testers), but I’d be interested to hear your opinion on jsmock and the ability to test pre-system using in-container (e.g. Jetty) or other methods (i.e. virtual mocking).
All these types of testing techniques are something I’d like to see turn instructional – a video would be good. A more complete section on testing and security in your new book project is also recommended.
Gareth and GNUCITIZEN are great people, I can vouch for them. You should highly consider working on projects with them, as I think they have some hero-worship going on.
Anthony Ettinger (February 2, 2008 at 2:48 am)
There’s a really good book out there about XSS co-authored by the founder of WhiteHat Security, Jeremiah Grossman.
“XSS Exploits: Cross Site Scripting Attacks and Defense” by Seth Fogie, Jeremiah Grossman, Robert Hansen, and Anton Rager.
http://tinyurl.com/yoxend
dre (February 6, 2008 at 12:39 am)
You might also want to include some of your previous discussion about security e.g. Javascript Fuzz Testing in your book. You can also see the full video talk from Blackhat with Window Snyder and Shaver from the Mozilla Project at this link to the MP4 download.