The function tryParseJSON() in editable-form-utils.js is dangerously bad. The regex used to test if a string is JSON is terribly made, only checking if the string begins and ends with "[" or "{" and their counterparts "]" or "}". This means you can give it a a string such as "[]+alert(1)+[]" and it will match. Once it's matched, tryParseJSON() decides to run the text as code by doing s = (new Function('return ' + s))();. When using that code with an actual JSON string s becomes an object based on the JSON string given. Using my evil alert string s is set to "undefined" and the number 1 is alerted on the screen.
I was able to exploit this on my site by setting an editable value to "[]+alert(1)+[]" and refreshing the page. When initially inserting it tryParseJSON() isn't used but it is when the editable field is initialised on load. For my site I opted to replace the new Function() call with a JSON.parse() call. This fix won't work for everybody though, as JSON.parse() is much stricter about what is and isn't allowed in a JSON string (e.g. all properties must be surrounded in double quotes and no trailing commas are allowed).
The function
tryParseJSON()
in editable-form-utils.js is dangerously bad. The regex used to test if a string is JSON is terribly made, only checking if the string begins and ends with "[" or "{" and their counterparts "]" or "}". This means you can give it a a string such as "[]+alert(1)+[]" and it will match. Once it's matched,tryParseJSON()
decides to run the text as code by doings = (new Function('return ' + s))();
. When using that code with an actual JSON strings
becomes an object based on the JSON string given. Using my evil alert strings
is set to"undefined"
and the number 1 is alerted on the screen.I was able to exploit this on my site by setting an editable value to "[]+alert(1)+[]" and refreshing the page. When initially inserting it tryParseJSON() isn't used but it is when the editable field is initialised on load. For my site I opted to replace the
new Function()
call with aJSON.parse()
call. This fix won't work for everybody though, asJSON.parse()
is much stricter about what is and isn't allowed in a JSON string (e.g. all properties must be surrounded in double quotes and no trailing commas are allowed).