I've just release version 0.3.1 of Cross Site Sniper. This is a minor bug fix update.

Cross Site Sniper is a Ruby on Rails plugin that automatically html escapes all string and text fields of ActiveRecord objects. Data is escaped as it is retrieved from the database to protect your site from XSS (cross site scripting) attacks without modifying or corrupting your original data. Convenience methods are provided to access the unescaped data when necessary. Edit forms are prepopulated with unescaped data as well to avoid user confusion and prevent double escaping.

Documentation and install instructions can be found at http://xss.rubyforge.org.

Comments: 0 [add comment]

I released CrossSiteSniper version 0.3 today with one small enhancement.

In v0.2, only instance methods directly associated with a column in the database had the ability to get the data without html escaping via the _without_html_escaping call. Now,thanks to the magic of method_missing, that works on all methods. So, imagine you have a method defined in your model that draws from one or more text fields in your table. Usually each of those fields will be escaped by CrossSiteSniper. But now, calling that same method with the '_without_html_escaping' suffix will temporarily turn off html_escaping just long enough to for that method to get all all it's data and return the unescaped result of whatever it does. It's not a feature most people will have a need for, but we did come across a need for it at the day job, so now you can use it too.

Comments: 0 [add comment]

Cross Site Scripting aka (XSS) is a common concern for web developers. In fact, anybody developing an interactive website, small or large, should be concerned about and guard against it.

What exactly is XSS? Simply put, it's devious people with ill intentions using your website as a host to do nasty things to the computers of other people who visit your website, and it's quite easy to create a website that just lets them do it. In fact, if you're not constantly thinking about it, you're probably guilty of leaving lots of opportunities open on you're site for the bad guys to do all kinds of bad stuff to your visitors, without you knowing anything about it. The more dynamic a site is with lots of user interaction, the more potential opportunities there are to mistakenly leave a hole open. So, what can you do?

The standard method in Rails is to wrap every piece of data that comes from a user submitted source in the h() method in the view to escape any html they may have included. Many experienced developers are have developed a good habit of always knowing when to wrap things in the h() method. But, I have a couple big problems with this.

  • First, it's very easy to forget, just once, and mistakenly leave some piece of data unprotected, and eventually a diligent hacker will find it. And that's all they need is one hole. Furthermore, there's nothing to warn you of the problem, before or after someone has taken advantage of it.
  • Next, one of the main philosophies of Ruby programming is Don't Repeat Yourself (DRY), and I'm sorry, but wrapping data in h() methods in your views and helpers over and over again is very, very repetitive. 99.999% of the time I want the data wrapped, so why can't Rails just do it for me, and let me define when the exceptions are, rather than the other way around?

This is certainly not a new topic, and there are a plethora of different attempts at solutions. Some are better than others, but none that I could find over the course of several months of looking for something that met the requirements that I thought were necessary.

First, it has to be automatic and it must work in both views and helpers. Everything that needs escaping should just be escaped and at just the right moment, without making me think about it. Next, it must be escaped on output. Some plugins that attempt to solve this problem opt to escape the data before it gets entered into the database. This has the advantage of only having the process the data once on input, rather than repeatedly every time it is output. However, I think escaping on output is much better because,

  • You're not going to inadvertently corrupt legitimate data in the database, since you're saving it exactly as submitted. So when users go to edit records, everything looks just like it did when they submitted it, instead of special characters turning into weird strings of other characters. And if you find that you want to use a more selective method of filtering a particular field, you can do so simply by changing the view and not worry about a bunch of records that already got escaped the old way. NOTE: I'm strictly taking aobut defending against XSS attacks here. You should still be using proper coding techniques to defend against SQL injection attacks, and that's well beyond the scope of this post. XSS and SQL Injection are two different things and should be dealt with separately. You should NOT be depending on one tool or technique to provide you with appropriate and adequate defense against both XSS and SQL Injection.
  • If a safer method of scrubbing data becomes available, you can instantly apply it to legacy data. With data escaped on the save, you'd need to loop through all the old records, try to unescape each one and reconstruct what was originally entered, then re-escape it with the new method. That is, unless you're comfortable with half the data in your database having been escaped with one method, and the other half with the other method? And what happens when one of those records escaped the old way gets edited and then re-escaped the new way. Ughhh.
  • What if you forget to escape something, or maybe you originally intended to do the repetitive h() method, but now that your app has been live for 8 months, you realize that was a dumb idea? Now you've potentially got a database full of unescaped or partially escaped data that you'll need to either escape on output like I recommend, or loop through every record and fix one by one (that's gonna be a very long running migration).

SafeErb is one solution that comes up a lot in blogs. But my problem with it is that it doesn't prevent me from having to wrap everything in h() methods. I just makes my application explode if I forget. That's certainly better than doing nothing, since I won't be able to forget to escape something, but it's not DRY.

Another suggestion I found was switching to Erubis as a rendering engine. The problem here is that it only provides the auto-escaping of raw data in views. So, I've got to constantly think about whether or not to put <%= or <%== depending on whether or not I'm calling a helper. Then, inside helpers I still need to remember to strategically call h(), hoping I haven't forgotten anything. In my opinion, this just makes things worse rather than better. Plus, my brief tests didn't appear to yield anything of the purported speed improvements that Erubis has over ERB. Integration tests ran just as fast.

xss-shield and xss_terminate are two more I found. In fact, xss_terminate didn't come to my attention until my contribution (below) was nearly finished. However, the problems here are that xss-shield still makes me do things manually in my custom helpers, and xss_terminate is one of those escape_on_save style solutions.

There's also a few whitelist plugins out there, but having to type whitelist() all the time is worse than h() if all I'm trying to to is prevent XSS attacks. There are certainly many more options I looked at but can't remember right now. Each one that I looked at though didn't sufficiently meet my requirements.

Lastly, when I was getting ready to submit my plugin (below) to rubyforge, I discovered the autoescape plugin. That's the closest I've seen to what I wanted, but it still had an issue that I didn't like. Since it escapes things right out of the database, edit forms pre-populate with the escaped data, rather than what the user originally entered. There are some work-arounds for this, but they require doing special stuff in your forms, and like I said, I don't want to have to think about it.

To cut an already long post short, last week at the day job I started on my own contribution to the long list of attempts to solve this problem, and now that it's done, I'm very happy with it. Sure, I'm biased, but it's the only Rails plugin I know of that meets all my requirements to adequately solve this problem. So, without further ado, I'd like to introduce Cross Site Sniper, a Rails plugin that automatically escapes every String and Text field in ActiveRecord classes, provides easy access to the unescaped data when needed and the ability to specially designate certain fields to remain unescaped. Big huge thanks to my supervisor Aaron Baldwin and World Wide IDEA for giving me the time to hammer this thing out and allowing me to release it to the world.

Not everyone will agree with my requirements. Some will still choose to escape on save and have good reasons for doing so. Other's will certainly prefer one of the above solutions, a combination of two or more, or some other solution I've overlooked, or one yet to come. And that's that great thing about open source software. None of these solutions would be possible without being able to peruse the source code of Rails, and because there's several options, you can pick the one that suits you best, or create your own. I just hope some Rails developers out there find Cross Site Sniper to be the the silver bullet they've been waiting for.

Comments: 2