Defending against cross-site scripting

We will go through the basic techniques of defending against cross-site scripting. This is by no means a comprehensive list of defenses against cross-site scripting, but it should be enough to get you started.

Do not trust users – parsing input by users

We can parse the user's input using various techniques. Since we are talking about JavaScript in this book, we can apply the following JavaScript function to prevent the execution of malicious code:

    function htmlEntities(str) {
        return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

This function effectively strips the malicious code from the user's input and output as normal strings. To see this function in action, simply refer to the source code for this chapter. You can find this function in use at python_server/templates/todos_secure.html. For ease of reference, the code snippet is being applied here as follows:

    function htmlEntities(str) {
        return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
    }

    function todoTemplate(title, body, id) {
      var title = htmlEntities(title);
      var body = htmlEntities(body);
      var snippet = "<div id=\"todo_"+id+"\"" + "<"<h2>"+title+"</h2>"+"<p>"+body+"</p>";
      var delete_button = "<a class='delete_item'  href='#' id="+id+">+">delete</a></div><hr>";
      snippet += delete_button;

      return snippet;
    }

Notice that the to-do item is first being escaped and returned as an HTML template for our app to insert into the browser screen.

Note

There are times when some HTML tags are allowed to be used for users. Some libraries help us do this, such as Google Caja (http://developers.google.com/caja).

Another approach is to make use of auto-escape or similar utilities to escape the input first. For instance, instead of using Ajax to get the output, you can simply generate the output from the server side. In Tornado's case, you can make use of the autoescape function. You can learn more about it at http://tornado.readthedocs.org/en/latest/template.html.

There are other ways and forms of protection as well:

  • HTML and JavaScript escaping/validating: We have done this already.
  • Cookie security: Although we did not cover it this chapter, it is possible to steal a user's cookie via the techniques we have described in this chapter. In this case, the defense will have to be done on the server side as well. For example, the backend server can only allow the cookie to be used in conjunction with the IP address the end user signed up with in the first place. This is generally useful, but not 100 percent foolproof. You may also use HTTP only flags in your cookies so that JavaScript won't be allowed to access them.
  • Disable scripts: This means you can either disable JavaScript or use as little JavaScript as possible. While disabling JavaScript is typically initiated by end users and because a lot of interaction is based on JavaScript, this might be difficult to achieve.