JavaScript Evaled JSON injection


Example

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 evaled:

({
    "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.

Mitagation

  • 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.