Let's say that whenever someone visits a profile page in Bob's website, the following URL is fetched:
https://example.com/api/users/1234/profiledata.json
With a response like this:
{
"name": "Bob",
"description": "Likes pie & security holes."
}
Than that data is parsed & inserted:
var data = eval("(" + resp + ")");
document.getElementById("#name").innerText = data.name;
document.getElementById("#description").innerText = data.description;
Seems good, right? Wrong.
What if someone's description is Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.
? Seems weird, but if poorly done, the response will be:
{
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
}
And this will be eval
ed:
({
"name": "Alice",
"description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS."
})
If you don't think that's a problem, paste that in your console and see what happens.
Use JSON.parse instead of eval to get JSON. In general, don't use eval, and definitely don't use eval with something a user could control. Eval creates a new execution context, creating a performance hit.
Properly escape "
and \
in user data before putting it in JSON. If you just escape the "
, than this will happen:
Hello! \"});alert(1);({
Will be converted to:
"Hello! \\"});alert(1);({"
Oops. Remember to escape both the \
and "
, or just use JSON.parse.