I've been using Ruby on Rails for a good year and a half now, but something I still remember from when I was just getting started was the lack of discussion about SQL injection or XSS issues. This isn't very surprising; in any language or framework the last thing you explain to beginners is a rousing study on security concerns. It's kind of sad, really, when you think about it. But so is life. Let's look at code.
Your basic ActiveRecord find goes something like this:
@articles = Article.find(:all)
That'll find all of your articles and populate them into @articles. Cool beans. Say you want to grab all the articles that are titled a certain way, which you have access to via params[:title]. There's a few ways of doing this. One way is to add :conditions.
@articles = Article.find(:all, :conditions => "title = #{params[:title]}")
So what you're doing is grabbing :title from your parameters and then directly tossing it in your query. Repeat with me: bad code. This is vulnerable to what's called an SQL injection attack, meaning anyone can come along and look for a post with the title of:
1; DROP TABLE super_cool_table;
So, like, don't do this.
One solution is to use ActiveRecord's magic, super-cool finder:
@articles = Article.find_by_title(params[:title])
This is fine. Rails automatically makes sure that any arguments you pass in won't be able to inject arbitrary SQL. For a bit more flexibility, I go the following route:
@articles = Article.find(:all, :conditions => [:title => params[:title]])
...or even:
@articles = Article.find(:all, :conditions => ["title = ?", params[:title]])
These are both a-okay. Rails sanitizes the parameters in each of these scenarios, so you can rest assured that you're not wide open to some ugly attacks.
I recently discovered a XSS hole in PayPal's own website, which theoretically would let me set up an attack that would let me steal your cookies, hijack your PayPal session, and do lots of Bad Things to your PayPal account and linked credit cards and bank accounts (probably involving hookers, a flight to Panama, and a fancy new yacht). (By the way— if anyone has a better idea of getting in touch with PayPal, let me know... it's surprisingly difficult to sift through regular customer support with issues like this.)
Anyway, I digress. For more information on XSS, check out the ever-popular Wikipedia article. You're here to combat XSS anyway, right? Let's get started.
In your views:
<%= h @article.title %>
That's it. The method "h" escapes any HTML that might be in your article's title that a wayward user might have submitted.
Granted, it's a bit of a pain in the ass. Django decided to auto-escape your values by default, and Rails does not. And the fun with XSS is that if you miss one of those little h method calls, well, you're screwed.
There's a few ways around that, though. One is to make sure you sanitize user input on the way into your app, so when you call it later on you know that you're safe. Another somewhat unequal way of doing things while maintaining interactivity (like embedded links and images) is to do the same thing I'm doing on this blog for its comments: allow users to use Markdown (or Textile) instead of HTML.
Another option is to go the plugin route and let it handle sanitization for you:
No one has commented yet.