Preventing XSS in Javascript strings

Escaping user-input in your HTML is essential for preventing worlds #1 vulnerability.

When you're embedding user input into javascript, a simple htmlspecialchars won't cut it, you'll need to make sure you're escaping other things, like \n (line endings), and \ (slashes). Google doctype has a good list of characters in need of proper escaping to prevent users breaking your javascript.

However, when I dropped the question if a simple string replacement would be good enough, the members of the Web security mailing list gave me a different answer.

When escaping or filtering output using a blacklist (such as the one published on google doctype) browser/unicode escaping bugs are not taking into consideration. Some new vulnerability might appear in the future, which would immediately open a hole in your app. For this reason its wiser to go with a much more defensive white-list approach, essentially only letting things through you know is safe.

Introducing Reform

Reform is a tool that does exactly this. Reform allows you to escape your data for a javascript, xml, html or vbscript (yes it still exists) context. It provides libraries for Java, .NET, PHP, Perl, Python, Javascript and ASP. Pretty cool!

One dislike I have is that it only considers I really small set of unicode codepoints safe, especially when dealing with non-latin languages this is going to add a great deal to the bandwidth usage and the legibility of your sourcecode. One would think there has to be more ranges considered 'safe'.

PHP example:

  1. <?php
  2.   // Assuming the Reform class is included..
  3.  
  4.   echo '<script type="text/javascript"> var myString = ', Reform::JsString($userInput), '; </script>';
  5.  
  6. ?>

I made a couple of changes in the PHP version, specifically:

  • Prepended the 'static' keyword to every method to make it work in PHP5's strict mode.
  • Removed the UTF-8 checks, I'm in a controlled environment, mbstring is installed, and the internal encoding is utf-8.
  • Added a parameter to Reform::JsString to not automatically put the string between quotes (').

3 Responses to Preventing XSS in Javascript strings

  1. 647 Steffen 2008-07-31 3:33 pm

    Shouldn't json_encode() be a simple and secure way to prevent XSS in JavaScript strings? http://php.net/json_encode

  2. 648 Evert 2008-07-31 4:14 pm

    Hey Steffen,

    Theoretically and according to javascript standards the answer would be yes.. However, this would not take unicode parser bugs or browser bugs into consideration (which have appeared over time).

    Supposedly the Reform library has never been affected by any of these bugs.

    Same could be said for htmlspecialchars..

    Evert

  3. 649 kL 2008-07-31 5:31 pm

    To output UTF-8 string in script tag:

    htmlspecialchars(json_encode($string))

    in this order.
    That's it. Really.

Leave a Reply



About

My name is Evert, and I've been writing semi-regularly on this blog since 2006.

I'm currently available for contract work.

more info.

Subscribe

Dropbox

Dropbox is a simple cross-platform online backup and sync application. The first 2GB of space is free, and both you and me get an extra 250MB extra space if you sign up through this link.