Reputation: 1178
This question has been asked many times. See here, here and here
Based on the answers in those questions I did some tests and I'm forced to ask the same question again as none of the answers appear to be correct (at-least to me). Please correct me if my understanding of subject is bad.
I'm working on an API for a web app that outputs JSON response. The server side response is handled by json_encode
in PHP. Since, this would be a public API I would want to prevent any XSS due to incorrect client side implementations by a deveopler consuming the API.
For my test I did the following on server side:
header("Content-Type: application/json", true);
$bad = array('bad_key' => 'alert("hi");');
echo json_encode($bad);
On client side I'm using jQuery AJAX that automatically parses the JSON recieved. Initially this did not appear to show any XSS issue. Then I passed response.bad_key
to eval()
.
eval(response.bad_key);
This immediately resulted in execution of string in bad_key
. I'm aware that use of eval
is bad and should be avoided. However, that's something that I know and cannot ensure the other developer follows the same practice. To avoid such scenarios a solution would be to perform server side encoding. For this let's say I use htmlspecialchars
.
header("Content-Type: application/json", true);
$bad = array('bad_key' => htmlspecialchars('alert("hi");'));
echo json_encode($bad);
This, though it does not execute alert("hi");
client-side but breaks the JS code due to presence of &
. json_encode
with the option JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS
as suggested here does not help either.
So how do I prevent XSS in such a scenario?
Upvotes: 1
Views: 1576
Reputation: 318568
You do not need to prevent "XSS" in this scenario. If someone is stupid enough to execute some random data you send him as JavaScript there is nothing you can do against it. Actually, if you did escape something to prevent it he would probably unescape it to make it work again.
Note that using eval
to parse the JSON string is somewhat safe (assuming you send valid JSON) - even though it's discouraged in any modern browser that has a native JSON.parse()
.
But in your example you do not use it to parse JSON but to execute some random string of data! When anyone does that it means that he WANTS it to be executed as code - so it's not XSS but "working as intended"!
Upvotes: 9