So Rob and others have both pointed out that I used the term JSON incorrectly when referring to approaches 2 & 3 in my "Safe JSON" post. They are, of course, completely correct those approaches are returning Javascript and not JSON.
That got me thinking though is JSON Javascript? JSON is absolutely a valid javascript "expression", but does a piece of JSON represent a complete Javascript "program" as defined in the Emcascript standard Chapter 14 (page 75), i.e. should JSON be executable? As far as I can make out from reading the spec, JSON is a valid Javascript program and the implications of this fact seem to render JSON pretty much useless as a data exchange format for any kind of private data.
Joe has already demonstrated that it is possible to get at data in a JSON array using a CSRF attack and went on to show that you could also do it for JSON objects. These attacks work as the JSON executes as a Javascript "program" when included by a <script> tag. However, he is kinda cheating. To get the object hack to work he had to surround the JSON with () as mentioned in the comments. So strictly speaking his attack doesn’t work on pure JSON objects on Firefox at the moment. When you try it with a pure JSON object you get a parse exception as I pointed out to Joe.
But here’s the question should it work?, and this brings us back to whether JSON is a valid Javascript program. If it is, and from reading the spec I think it is *blush* it isn’t, then firefox should really fix the bug that is incorrectly parsing a JSON object when included as a piece of Javascript via a <script> tag and Joe would no longer need to place the JSON object in () to get the object attack to work.
It appears that a data interchange format has been "conflated" with an executable program and as such we have a huge gaping hole in the security of using JSON as a data exchange format.
I hope I am wrong about this, but it was interesting to discover that the guy that wrote the JSON RFC has tried to tighten the javascript standard and in his verifier JSON is NOT a valid javascript program. Maybe he knows something the rest of us are just figuring out.
As an aside connections will NOT be offering a JSON api.
Update So Lenny’s comment had me take a second more detailed look at the ECMAScript spec and it appears that JSON Object Literals are safe, more out of luck than by design. JSON Object literals are valid "Expression" Chapter 11 p40 and so I incorrectly inferred that they were "Expression Statements" Chapter 12.4 p63 . However the spec clearly states "Note that an ExpressionStatement cannot start with an opening curly brace because that might make it ambiguous with a Block." and so parsers should infer that the contents of the JSON Object Literal to be a block and as the contents of JSON Object Literals are not valid Blocks it should error out.
Lenny summarizes it well.
"As I see it, the takeaway from all this is that the root of any private JSON document should be an Object, never an Array <snip/> Prescription: don’t start your JSON doc with [, and don’t deviate from the spec with things like parentheses."
“connections will NOT be offering a JSON api.” I assume you mean that JSON is not a data format that connections APIs will accept as input, or generate as output. That’s too bad. XML only? YAML, perhaps?
XML only for the first release, in the form of Atom Feeds and the Atom Publishing Protocol.
As I see it, the takeaway from all this is that the root of any private JSON document should be an Object, never an Array.
{…}, when not wrapped in parentheses, is interpreted as a code block rather than an object literal, so executing it will fail as a parse error. Wrapping in parentheses isn’t valid JSON, anyway, so don’t do it and you should be safe. Like you said, it’s not a Javascript program.
[…], the other valid root, is a Javascript program, and is as vulnerable as ever.
Prescription: don’t start your JSON doc with [, and don’t deviate from the spec with things like parentheses.
If you read John Resig’s article “Native JSON support is required” ( http://ejohn.org/blog/native-json-support-is-required/ ) you’ll see that we’re just on the cusp of JSON being very mainstream. The next generation of browsers will have cross-domain support for json and it’s implied in the spec that the data will be processed by the browser and placed into a javascript object meaning you won’t need to write a javascript serializer or pass the json data through eval (and we all know that i is masquerading as an a in that word).
So like it or hate it, json’s position in web-applications is only going to get stronger over the coming year. The standards are in place and the browsers are lining up to support it and I think in the end it will be a good thing, finally allowing data to be retrieved cross domain safely and securely for both the client and server.
Isn’t the moral of this tale that “eval is not a demarshaller”? I mean, c’mon — couldn’t the Moz/IE/ECMAScript foks add a “parse” builtin function to the standard, that didn’t eval? Perhaps one that only accepted the constant-expression part of the Javascript grammar?