No, but if I do `var a = new Array();` I can have that put up an alert. The Resig post linked to above indicates that FF will complain if you try to redefine the Array function, which is not what I'm seeing FF 20 (beta channel) and Chrome 25.
This will throw an exception, because the browser doesn't allow the cross domain requests to http://bank .
However, he _can_ insert a <script> tag that loads it (this is how JSONP works):
<script src="http://bank/sensitiveData"></script>
This will load your sensitive data (assuming you have a session open). If, before this, the attacker has overridden the Array constructor in his site's Javascript, whatever code he has in that constructor will receive your sensitive data (and may send it to his malicious database).
Now, if my bank data API actually served your sensitive data as executable Javascript, that is:
var bmjsSensitiveData = new Array("bmjs", "sensitive", "data");
Then you need to cancel your account and find a new bank immediately :) This would be loadable with the <script> tag on a malicious site as shown earlier, and subsequently make the variable bmjsSensitiveData available to the attacker's Javascript (overriding the Array constructor wouldn't even be necessary).
however it's still best to protect your secure data with un-predictable URLs.
Please, please, no. This is terrible advice - do not rely on security by obscurity! This is not even obscure - anybody can open the network monitor in Chrome and get the URL. You should be doing exactly the opposite - publish your URLs and get researchers to investigate them. Give a bounty if they break it and you'll have tons of researchers all happily fixing your security for you! Do not obscure this stuff.
I think the point is that each user's data should have its own URL, not that anyone should be able to get all the data from one URL. It doesn't matter if the user can get the URL; it points to their data, which they can get anyway. What matters is whether another website can get the URL and then pull the data out with a script tag, which is impossible if said website can't predict the URL.
You could also accomplish this by encapsulating things in an object literal (as suggested on the page); requiring POST or a header or returning a non-JS Content-Type; loading an HTML page on the site and using window.postMessage to send the data only to trusted sites; and maybe more ways as well.
My interpretation is that you should have URLs tied to data that is out of reach of the attacker. Instead of
http://myapp.com/me/contacts.json
You'd have
http://myapp.com/contacts/8df02390908dsf
Where '8df02390908dsf' could be a hash computed from the user's data, but a simple unique ID would suffice - as long as it's stored in document.cookie/localStorage where the third-party website can't access it.
While it's great to have that as an extra layer against attacks, as with all security by obscurity, the problem is when you rely on that detail to act as your security. If that hash is computed from the user's data, in 5 years time when they need to expose new data to some new platform, they may mistakenly choose to use that hash. Now every attacker has access to that hash - and your security that relied on keeping the hash secret is now wide open. There are many other possibilities of losing secrecy of a public url hash like this also.
The advice is still bad. Rather make your URL as open as possible and actually secure it for an attacker who happens to know it. If a user gets hacked and your response is 'well, nobody should have known the users ID!' then you're going to be looking pretty dumb.
This is why Google, Facebook, and others prepend JSON responses with while(1){}. Any browser trying to eval it will get stuck in an infinite loop, protecting the payload. That's what they did a couple years ago at least. It looks like gmail is now prepending with )]}' for some JSON calls instead.
I've been prepending with ], which as far as I know is enough to make any JSON data into a syntax error... is there a reason why these companies use longer things?
Well, data has no inherent security or insecurity. But anyone expecting a format that revolves around being able to be evaluated by javascript to be MORE secure is living in a fantasy world.
This statement is strictly true: JSON is unsafe for
anything but public data unless you are using
unpredictable URLs. It is true for all data formats.
There was never a good reason to believe that JSON
reduced the need for vigilant design.
Your session based generated HTML (i.e. Your Credit Card usage history) is safe against these kind of attacks, also guess what your XML is safe as well and all other data formats that cannot be called and interpreted by JavaScript from another domain. Heck even session based generated images are safe and cannot be read from another domain, other than some rare bugs (they are security bugs and will be fixed, not design issues).
Douglas Crockford was wrong. This was a real issue back in 2007 that was specific to JSON. A proof of concept exposed gmail contact lists. It is not true for all data formats.
Douglas Crockford defends JSON to the point of making himself look foolish. He causally dismissed this real issue as a non issue, and has done the same with the U+2028/9 line ending issue.
Edit: It is worth pointing out that Google still prefixes their JSON with )]}' to protect users that are still using 2007 browers.
That's why google starts their json with while(1); (or something like that) so any effort attempting to evaluate the json itself as javascript code will be stuck in an infinite loop.
XSS restrictions generally apply to things such as making XmlHttpRequests from other sites. Loading scripts from other sites generally isn't restricted, since it's used for a variety of legitimate things such as loading jQuery from a CDN.
Knowing that all user-data is required to have a user-credential, use this fact when issuing the urls to the browser that instantiate this request, make these urls specific to the user and cryptographically bound to their authenticated state.
session_id = '5f5513f8822fdbe5145af33b64d8d970dcf95c6e'
ajax_endpoint_secret = 'this is a super secret!'
Here, we have cryptographically bound the AJAX url to the user's cookies, so the <script> trick won't work any longer as they don't have access to the token.
Second, you can have your server endpoint checking for the 'X-Requested-With: XmlHttpRequest' if you anticipate this to only be accessed via XHR. This is a pretty effective thwart of the <script> attack as well.
Lastly, ensure that your JSON response always is wrapped in curly braces {}. Never respond with [] From my experiments, all browsers interpret this as a code block and breaks processing when <script src=> runs.
Now I have effectively stolen your user's credit card transactions from your site. You see, from your server's point of view, the user is logged in and is connecting over SSL.
This is mitigated by modern browsers that don't allow rewriting the array constructor. If you care about users using FF 2.0, then you need XSRF protection. Many frameworks build this in by default.
I can't speak for JSON, but can someone try the same for JSONp[1], which many (legit) services use to bypass the same-origin policy?
For example,
Your app - sends request -> Third party service
Third party service - replies -> JSONp response
Evil website's script on your app -> Hijack/modifies JSONp response -> steals credentials.
Is this possible? In all probability, it should be possible, right?
CORS does nothing to address this problem. If you expose private data via CORS or JSONP you face the exact same problem.
CORS solves a different problem, in that you don't have to eval 3rd party code. If the remote service provider gets hacked, then your site may not get compromised.
The issue is an external file can be called from a 3rd party website via "<script src=" and if the format is something that JavaScript interpreter understands then it's possible to hijack the data (so called JavaScript/JSON Hijacking).
CORS solves it because you can WHITELIST the domains that can access the data, which is huge! Just like crossdomain.xml in Flash and ContenPolicy in Silverlight.
You are right though if the format is still JSON you are still vulnerable to the same attack, however CORS doesn't require you to use any format particularly, so it's possibly to use any other data format.
I don't think JSON is safe. In fact, as any good developer should with most technologies, I assume it's unsafe... that way I stand a better chance of securing my apps.
A commenter on that page claims that having an array at the top level is not valid JSON, but they're wrong. The RFC (found at http://www.ietf.org/rfc/rfc4627.txt?number=4627) defines the root nonterminal in the JSON grammar as:
So is the solution to this to use the double-cookie send or nonces as the article states? I've been doing that in all my AJAX calls just to ensure no XSRF possibilities exist.
AFAIK, the ability to override the Array constructor has been fixed in all modern browsers.
Here's a blog post by John Resig about the same issue: http://ejohn.org/blog/re-securing-json/ (also from 2007).