John
John

Reputation: 1178

PHP json_encode and XSS

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

Answers (1)

ThiefMaster
ThiefMaster

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

Related Questions