简体   繁体   中英

Is it possible to XSS exploit JSON responses with proper JavaScript string escaping

JSON responses can be exploited by overriding Array constructors or if hostile values are not JavaScript string-escaped.

Let's assume both of those vectors are addressed in the normal way. Google famously traps JSON response direct sourcing by prefixing all JSON with something like:

throw 1; < don't be evil' >

And then the rest of the JSON follows. So Dr. Evil cannot, using the sort of exploit discussed here http://sla.ckers.org/forum/read.php?2,25788 get your cookie (assuming you're logged in) by putting the following on his site:

<script src="http://yourbank.com/accountStatus.json"> 

As for string escaping rules, well if we're using double quotes, we need to prefix each with a backslash and each backslash with another backslash etc.

But my question is, what if you're doing all of this?

Burpsuite (the automated security tool) detects embedded XSS attempts that are returned unHTML-escaped in a JSON response and it reports it as an XSS vulnerability. I have a report that my application contains vulnerabilities of this kind but I am not convinced. I've tried it and I can't make an exploit work.

So I don't think this is correct, but I ask you StackOverflow community, to weigh in.

There is one specific case, that of IE MIME-type sniffing that I think could result in an exploit. After all, IE 7 still had the "feature" that script tags embedded in image comments were executed regardless of the Content-Type header. Let's also leave such clearly stupid behaviour aside at first.

Surely the JSON would be parsed by either the native JavaScript parser (Window.JSON in Firefox) or by an eval() as per the old default jQuery behaviour. In neither case would the following expression result in the alert being executed:

{"myJSON": "legit", "someParam": "12345<script>alert(1)</script>"}

Am I right or am I wrong?

This potential xss vulnerability can be avoided by using the correct Content-Type . Based on RFC-4627 all JSON responses should use the application/json type. The following code is not vulnerable to xss, go ahead test it:

<?php
header('Content-type: application/json'); 
header("x-content-type-options: nosniff");
print $_GET['json'];
?>

The nosniff header is used to disable content-sniffing on old versions of Internet Explorer. Another variant is as follows:

<?php
header("Content-Type: application/json");
header("x-content-type-options: nosniff");
print('{"someKey":"<body onload=alert(\'alert(/ThisIsNotXSS/)\')>"}');
?>

when the above code is viewed by a browser the user was prompted to download a JSON file, the JavaScript was not executed on modern versions of Chrome, FireFox and Internet Explorer. This would be an RFC violation.

If you use JavaScript to eval() the JSON above or write the response to the page then it becomes DOM Based XSS . DOM based XSS is patched on the client by sanitizing the JSON before acting on this data.

Burpsuite (the automated security tool) detects embedded XSS attempts that are returned unHTML-escaped in a JSON response and it reports it as an XSS vulnerability.

Maybe it tries to prevent the vulnerability described in the rule 3.1 of OWASP XSS Cheat Sheet .

They give the following example of vulnerable code:

<script>
    var initData = <%= data.to_json %>;
</script>

Even if double quotes, slashes and newlines are properly escaped, you can break out of JSON if it's embedded in HTML:

<script>
    var initData = {"foo":"</script><script>alert('XSS')</script>"};
</script>

jsFiddle .

to_json() function can prevent this issue by prefixing each slash with a backslash. If JSON is used in HTML attribute, the whole JSON string must be HTML-escaped. If it's used in a href="javascript:" attribute, it must be URL-escaped.

For the record, although I accepted an answer, for the exact literal question I am asking, I was right and there was no vulnerability due to the presence of non-HTML-escaped yet correctly JSON-escaped HTML inside JSON values. There could be a bug there if that value was inserted into the DOM without client-side escaping but Burpsuite has little chance of knowing if that would happen just by looking at network traffic.

In the general case of determining what is a security vulnerability in these circumstances, it's instructive to recognise that while it may not feel like good design, the response content of a JSON value could legitimately be known to certainly contain no user input and be intended to be already rendered HTML to be safely inserted in the DOM unescaped. Escaping it would be a (non-security) bug as I mentioned in another comment.

If we limit our scope to IE (all versions), assume you are running a site based on PHP or ASP.NET, and ignore the IE anti-xss filter, then you are wrong: your users are vulnerable. Setting 'Content-type: application/json' will not help, either.

This is due to (as you mention) IE's content detection behavior, which goes beyond sniffing for HTML tags in the response body to include URI analysis.

This blog posting explains this very well:

http://blog.watchfire.com/wfblog/2011/10/json-based-xss-exploitation.html

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM