天天看點

SON Hijacking

<a href="http://www.sxc.hu/photo/676972"></a>

Before I go further, let me give you the punch line first in terms of what this vulnerability affects.

This vulnerability requires that you are exposing a JSON service which…

…returns sensitive data.

…returns a JSON array.

…responds to GET requests.

…the browser making the request has JavaScript enabled (very likely the case)

…the browser making the request supports the <code>__defineSetter__</code> method.

Thus if you never send sensitive data in JSON format, or you only send JSON in response to a POST request, etc. then your site is probably not vulnerable to this particular vulnerability (though there could be others).

I’m terrible with Visio, but I thought I’d give it my best shot and try to diagram the attack the best I could. In this first screenshot, we see the unwitting victim logging into the vulnerable site, and the vulnerable site issues an authentication cookie, which the browser holds onto.

At some point, either in the past, or the near future, the bad guy spams the victim with an email promising a hilariously funny video of a hamster on a piano.

But the link actually points to the bad guy’s website. When the victim clicks on the link, the next two steps happen in quick succession. First, the victim’s browser makes a request for the bad guy’s website.

The website responds with some HTML containing some JavaScript along with a<code>script</code> tag. When the browser sees the script tag, it makes another GET requestback to the vulnerable site to load the script, sending the auth cookie along.

The bad guy has tricked the victim’s browser to issue a request for the JSON containing sensitive information using the browser’s credentials (aka the auth cookie). This loads the JSON array as executable JavaScript and now the bad guy has access to this data.

To gain a deeper understanding, it may help to see actual code (which you can download and run) which demonstrates this attack.

<code></code><code></code>

<code></code>

Notice that I’m requiring authentication via the <code>AuthorizeAttribute</code> on this action method, so an anonymous GET request will not be able to view this sensitive data.

The fact that this is a JSON array is important. It turns out that a script that contains a JSON array is a valid JavaScript script and can thus be executed. A script that just contains a JSON object is not a valid JavaScript file. For example, if you had a JavaScript file that contained the following JSON:

{"Id":1, "Balance":3.14}

And you had a script tag that referenced that file:

<code>&lt;script src="http://example.com/SomeJson"&gt;&lt;/script&gt;</code>

You would get a JavaScript error in your HTML page. However, through an unfortunate coincidence, if you have a script tag that references a file only containing a JSON array, that would be considered valid JavaScript and the array gets executed.

Now let’s look at the HTML page that the bad guy hosts on his/her own server:

Note that this attack does not work on IE 8 which will tell you that <code>__defineSetter__</code>is not a valid method. Last I checked, it does work on Chrome and Firefox.

The mitigation is simple. Either never send JSON arrays OR always require an HTTP POST to get that data (except in the case of non-sensitive data in which case you probably don’t care). For example, with ASP.NET MVC, you could use the<code>AcceptVerbsAttribute</code> to enforce this like so:

With ASP.NET MVC (and other similar frameworks), a significant number of developers are not using client generated proxies (we don’t have them) but instead using jQuery and other such libraries to call into these methods, making the “d” fix kind of awkward.

Some of you might be wondering, “why not have the JSON service check for a special header such as the <code>X-Requested-With: XMLHttpRequest</code> or <code>Content-Type: application/json</code> before serving it up in response to a GET request?” I too thought this might be a great mitigation because most client libraries send one or the other of these headers, but a browser’s GET request in response to a script tag would not.

The problem with this (as a couple of co-workers pointed out to me) is that at some point in the past, the user may have made a legitimate GET request for that JSON in which case it may well be cached in the user’s browser or in some proxy server in between the victim’s browser and the vulnerable website. In that case, when the browser makes the GET request for the script, the request might get fulfilled from the browser cache or proxy cache. You could try setting <code>No-Cache</code>headers, but at that point you’re trusting that the browser and all proxy servers correctly implement caching and that the user can’t override that accidentally.

Of course, this particular caching issue isn’t a problem if you’re serving up your JSON using SSL.

But at the end of the day, assigning blame doesn’t make your site more secure. These type of browser quirks will continue to crop up from time to time and we as web developers need to deal with them. Chrome 2.0.172.31 and Firefox 3.0.11 were both vulnerable to this. IE 8 was not because it doesn’t support this method. I didn’t try it in IE 7 or IE 6.

It seems to me that to be secure by default, the default behavior for accessing JSON should probably be POST and you should opt-in to GET, rather than the other way around as is done with the current client libraries. What do you think? And how do other platforms you’ve worked with handle this? I’d love to hear your thoughts.

本文轉hackfreer51CTO部落格,原文連結:http://blog.51cto.com/pnig0s1992/733007,如需轉載請自行聯系原作者

繼續閱讀