Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to encode an inline javascript object, in order to protect it from XSS?

It turns out the following which looks like valid javascript, is not:

<html> 
<body>
<script>
 json = {test: "</script><script>alert('hello');</script>"};
</script>
</body>
</html>

The same text, when returned JSON via an ajax api works just as expected. However when rendered in-line results in a basic XSS issues.

Given an arbitrary correct JSON string, what do I need to do server side to make it safe for in-line rendering?

EDIT Ideally I would like the fix to work with the following string as well:

json = {test: "<\/script><script>alert('hello');<\/script>"};

Meaning, I have no idea how my underlying library is encoding the / char, it may have chosen to encode it, or it may have not. (so its likely a regex fix is more robust)

like image 611
Sam Saffron Avatar asked Aug 16 '10 00:08

Sam Saffron


2 Answers

See OWASP's XSS prevention guide (See Rule #3) -

Except for alphanumeric characters, escape all characters less than 256 with the \xHH format to prevent switching out of the data value into the script context or into another attribute. Do not use any escaping shortcuts like \" because the quote character may be matched by the HTML attribute parser which runs first.

Assume this is how your object looks like -


var log = {
trace: function(m1, m2, m3){},
debug: function(m1, m2, m3){},
currentLogValue : "trace {].a23-%\/^&",
someOtherObject : {someKey:"somevalue", someOtherKey:"someothervalue"}
};

This should end up like this -


var log = {
trace : "function\x28m1,\x20m2,\x20m3\x29\x7B\x7D",
debug : "function\x28m1,\x20m2,\x20m3\x29\x7B\x7D",
currentLogValue : "trace\x20\x7B\x5D.a23\x2D\x25\x5C\x2F\x5E\x26",
someOtherObject : {someKey : "somevalue", someOtherKey:"someothervalue"}
};

The rules are straightforward -

  1. Untrusted data is only allowed within a pair of quotes
  2. Whatever is within quotes gets escaped as follows - "Except alphanumeric characters, escape everything else with the \xHH format"

This ensures that untrusted data is always interpreted as a string, and not as a function/object/anything else.

like image 53
Sripathi Krishnan Avatar answered Oct 25 '22 15:10

Sripathi Krishnan


To start with, this is not JSON at all, it's a Javascript object. JSON is a text format that is based on the Javascript syntax.

You can either make sure that the code doesn't contain the </ character combination:

var obj = { test: "<"+"/script><script>alert(\"hello\");<"+"/script>" };

Or if you are using XHTML you can make sure that the content in the script tag is interpreted as plain data:

<script type="text/javascript">
//<![CDATA[
var obj = { test: "</script><script>alert(\"hello\");</script>" };
//]]>
</script>
like image 42
Guffa Avatar answered Oct 25 '22 14:10

Guffa