There is No Escape! (Actually There is and You Should Always Use It.)

· Read in about 4 min · (804 Words)

Beware Your Users:

Every developer should already know about, and work to prevent, scripting attacks on their site. Scripting attacks are one of the easiest ways for a hacker to attack your site, they are also one of the easiest attacks to prevent.

Whenever you let an end user enter text into a form on your site, and then display that text to other users on your site, you’ve opened yourself up to this sort of attack.

What can a hacker do in these sorts of attacks? Well, they can run malicious JavaScript that appears to the world to have come from your site. That means they can read cookies? Alter the page and ask for things such as passwords, credit card numbers, etc… All the while the end user believes these requests are coming from your site. That’s not good.

So how do you prevent against this? Well, you should always escape any text that orginally came from an end user to get rid of any <script> tags for a start. I would say go all out and get rid of, or escape, anything inside of < or > brackets.

A lot of web frameworks are trying to build this in now, to make it easier for developers to protect against such attacks. For example, in Rails all data that comes from the database is considered tainted and will be automatically escaped when displayed to the screen. The developer has to go out of their way to tell Rails that a particular string is safe. I, personally, really like this approach.

Lately I’ve been doing a lot of work with Backbone.js, it has replaced the view layer in Rails for me. When working with a Backbone model if you want to get an attribute you would normally call the get function. Let me demonstrate:

var model = new Backbone.Model({foo: "Bar"});

That code will set the h1 tag on the page to whatever the value of the attribute foo is, in this case the value «Bar». That’s all fine and dandy, but what if we set the value of the foo attribute to something a bit more malicious:

var model = new Backbone.Model({foo: "<script>alert('xss')</script>"});

If we were to run that code this time we would get an alert window that said xss. Not the worse thing that can happen, but it’s still pretty darn bad!

How can you prevent this from happening when using Backbone? Stop using the get function! There are only two places where I can see ever using the getfunction, and I’ll get to those in a second.

escape is Your Only Option:

To prevent these sorts of scripting attacks when using Backbone, you should be using the escape function. It essentially behaves just like the get function, but it will return an escaped version of the attribute.

If we were to update the malicious code example to look something like this:

var model = new Backbone.Model({foo: "<script>alert('xss')</script>"});

when it is run we would end up with an h1 tag that had a value of &lt;script&gt;alert(&#x27;xss&#x27;)&lt;&#x2F;script&gt;

Now, I’ll be the first to admit that doesn’t look very pretty, but at least the scripting attack has failed.

When You Should Use get:

Earlier I mentioned there are two places where I could see using the get function.

Because the escape function is santizing the value of the attribute for you there is a slight performance overhead, therefore, if you are definitely not going to executing the value of that attribute, then using the get function is acceptable. For example if you were doing something like the following:

var model = new Backbone.Model({foo: "Bar"});
if (model.get("foo") != null) {

Notice how there I used the get function to check whether the attribute’s value was null and then I used the escape function to actually print out that value. That is a perfectly acceptable use of the get function. It also, happens to the exact reason for use case number two.

The second reason you would want to use the get function has already been highlighted in the previous code example. The get function returns the original attribute value, unaltered. The escape function, however, will always return a string value, even if the original value was null.

var model = new Backbone.Model({});
console.log(model.get("foo")); // null
console.log(model.escape("foo")); // ""

See the difference there? I believe this to be a bug. I’ve submitted a pull request to fix this issue, so hopefully it’ll be resolved shortly. Because of this if you are doing any sort of comparisons, boolean checks, etc… always do it with the get function. If you are executing the value, such as printing it to the screen, always use the escape function.

Your users will be happier, and you’ll sleep better, if you always use the escape route!