views:

318

answers:

2

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:

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?

+1  A: 

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'); 
print $_GET[json];
?>

If you use JavaScript to eval() the json response or write the response to the page then it becomes Dom Based XSS. Although this is an avoidable vulnerability that can crop up for other reasons.

Rook
OK so I suppose I could have made it clearer, but the JSON response I'm talking about is defined by the presence of the Content-Type header having the value "application/json". So it seems you're confirming that there is no exploit.Can't your code can be exploited by direct sourcing on a hostile domain, that is using the script tag and parametising the source to include code that will then be executed in the context of the domain it's from? In that case that domain's cookies would be accessible and could be captured by the calling page using document.write. Right?
Chris Mountford
@Chris Mountford the injected JavaScript is not executed because the server is telling the browser not too. Think of it like this, what if you had JavaScript in a .exe? This *could lead* Dom Based XSS, but so could other designs. Dom based xss executes with the same policy as it is executed from. The only way that this can be a problem for you is if you are `eval()`ing the code on your own site.
Rook
My understanding was that JSON was eval()'d very commonly in the past, at least by default on jQuery (as I said). However, I'm interested not in JavaScript injection but in HTML injection in JSON which leads to JavaScript execution. Can you comment on that? Also, as I said IE as recent as v7 I have confirmed can IGNORE the Content-Type header under certain circumstances. Yes this is a bug in IE but Microsoft argued no (regardless of the RFC) and in the end, for security ,it only matters what the browsers do not what the spec says.
Chris Mountford
@Chris Mountford The term "js injection" is really bad and I shouldn't have used it, its always XSS and thats the correct term. It is possible to `eval()` code and have js stuck as data for instance `var test='<script>alert(/not_xss/)</script>'`, if the attacker can inject a single-quote then he can break out and execute javascript. If IE is executing JavaScript in .exe files or other in `application data` then they should be issued a CVE number. If you can prove this behavior I'll help you submit a Bugtraq post.
Rook
Thanks for that. For the record, I think javascript injection is an excellent term to disambiguate on one hand the use of the single quote for an escape in situations like this (which I specifically excluded from my original question) and on the other hand, the insertion of html tags to get into a script block.
Chris Mountford
+1  A: 

Why not just used the JSON.parse(response)? I think every major browser now supports it, and it does not execute any code it only reads objects and arrays.

qw3n
I think you're completely misunderstanding the question.
Chris Mountford
Sorry, I think I understand the question. And the only way I see some JSON response containing HTML being executed is if it is appended to the DOM. Eval and JSON.parse would treat it only as a string.
qw3n
Actually if it is appended to the DOM I think you will find it will be HTML escaped except in the case where it is set using innerHTML. One key focus of the question is whether the browser would ignore the Content-Type header such that a malicious site can source the JSON using a script tag. This is the reason for the executable tarpit in the preamble to the JSON. In this case it doesn't matter what the normal method of parsing the response is, it only matters whether the browser will ever possibly HTML parse it and THEN due to the script tag, execute the code in the JavaScript engine.
Chris Mountford