Consider this:
1 2 3 4 5 |
J = '{ "function X () { document.writeln(); }" : "hack" }' O = JSON.parse( J ) for ( var n in O ) eval( n ) ; X() |
This is possible because JSON names, not values, can be strings. One can type whatever she wishes to type, all the way to the biggest possible string length for her browser.
One can send to the browser client a lot of dangerous code hidden as a name in JSON string. It will be happily parsed into Object, with no problems whatsoever …
Simply saying: There is no concept of well formed JSON. As there is for XML. Whatever is sent is dutifully transformed into an JavaScript Object.
Some of the implementations do check that functions are not passed as values, but here I am passing the function hidden as a name, not as a value. Try this. It works.
One can say that without last two lines there is no attack on the client. True. The hackers just have to inject a very innocent code into the page, in another sending, after the malicious JSON was sent, and passed through, because it is legal indeed.
This is a problem. This makes JSON much less viable for safe SOAP messages, or simillar roles. where JSON rightly hopes to replace xml.
Why is this allowed? JSON itself has to be changed to be taken seriously for enterprise IT systems. Just do not allow names to be strings. Have same rules for JSON names as for javascript variables. And have JSON.parse()
throw an exception if name is an ECMA reserved keyword.
On the same subjec. IE8 arrives with “native JSON support”. Very good. Consider this IE8 snippet :
1 2 3 4 5 6 7 |
o = JSON.parse(<span class="string">'{ "null" : "the null value" }'</span>) ; o.<span class="keyword">null</span> <span class="comment">/* SyntaxError Number : 1010 Description : Expected identifier */</span> |
I think that IE8 JSON.parse() has (had?) the opportunity to be less fast and more safe?
The example above should throw an exception wtih the explanation of where and what is the illegal part of the JSON string. Exactly the same as IE does when opening an XML file which can not be parsed.
ALSO! IE8 JSON object, should have the functionality to load and parse the (json) files. Same as we currently have for xml files, with XMLDocument . Something like this would be very usefull :
1 2 |
<span class="keyword">var</span> obj = JSON.load( <span class="string">"person.json"</span> ) |
Above will load the text file (from the same domain) and try to parse its content as json string. Again, it must throw an exception in case of json parsing error.
Above can be all done with javascript of course, but not as fast as with IE native JSON support. And of course, this JSON object must be implemented by each and every browser, with exactly the same interface.
Regards …
4 thoughts on “JSON considered unsafe ?”
The first example only shows that it’s dangerous to blindly eval untrusted data. How you encode that piece of data doesn’t matter. XML/SOAP do not stop you from making the same mistake.
The second example regarding IE8’s JSON support is utterly wrong and irrelevant. It’s the second line (o.null) that violates the JavaScript syntax.
You, sir, are barking up the wrong tree.
@zw
Thank you for your comment. I know that
o.null
is not a valid javascript. But that is not the point.The whole point I am making is: If something “utterly wrong and irrelevant” can be sent as JSON stringm, then why is it allowed? What is the point of allowing a name to be called “null” when null is the reserved word ? why not just remove names as strings from JSON?
Also please remember that in large web applications it is impossible to “see” each and every JSON message. JSON will be not used only in “one developer and his page” situations. The whole enterprise messaging systems can be built on JSON. But right now, it is very unlikely, until people start realising its security deficiencies and start removing them. No security architect will allow JSON after seeing these examples.
Such a loophole is unthinkable to pass as “enterprise class” computing.
Your argument makes sense. Would this security flaw in JSON apply to Cross Domain YQL pulls? I am not a professional but only a dabbler, and my current interest is cross domain ajax. Thanks.
I am not 100% sure about YQL Cross Domain, but it should be pretty easy to knock up a page at (for example) JSBIN, to test this.
Just include “jQuery latest” and fire away…