I’ve recently been doing a bit of Rails auditing, and I thought that I’d just run through the main things I check; all fairly generic attacks that aren’t specific to particular Rails websites.
SQL injection
Actually, I haven’t seem much of this, probably because it’s one of the more well known attacks and people generally seem to be aware of it.
ActiveRecord will automatically escape any tainted data, but only if you use the correct syntax:
User.find(:all, :conditions => ['name = ?', params[:name]])
All the question marks will get replaced by the escaped name parameter, so your SQL query will be immune to SQL injection attacks.
However, if you were do do something like this:
User.find(:all, :conditions => ["name = #{params[:name]}”])
Well, you might as well be giving away your database credentials - an attack can post arbitrary SQL to your webserver, which it will happily execute.
However, it’s not just the :conditions options that is at risk - people sometimes forget to escape tainted strings when passing to :order and :limit (amongst others).
CSRF (Cross Site Request Forgery)
I’ve covered this before on my blog, and the problem has largely been solved with Rails’ built in protection against such attacks.
However, if you’re using GET requests to change state or make destructive actions you’re still at risk. A tell-tale sign is if they’re using :any in routes.rb - and not checking the request method in the controller action, for example:
# routes.rb:
map.resources :users, :member => {:approve => :any}
# user_controller.rb
def approve
User.find(params[:id]).approve!
redirect_to :action => ‘index’
end
So if Bob gave Alice a url to http://example.com/users/1/approve - Alice would automatically approve that user (if she was logged in).
Usually this attack would be done with a hidden image, so Alice would visit Bob’s innocuous website completely unaware that she had just sent of a request to example.com, approving Bob’s account.
It’s also worth searching for ’skip_before_filter :verify_authenticity_token’ - to see if CSRF has been disabled anywhere.
So, to sum up, make sure the site you’re auditing is using the right HTTP methods, for the right actions; and make sure it’s using an updated Rails version (or using the CSRF killer plugin).
Cross Site Scripting (XSS)
An attacker can exploit XSS to steal session cookies and/or write arbitrary HTML into your website.
If you have any unescaped tainted strings (from the database, for example) displaying on your website, then your site is vulnerable.
Do a search for ‘<%=’ on the codebase to quickly find potentially dangerous strings, if the string is tainted (e.g. from params or the db), then it needs to be wrapped in the ‘h’ method, like this:
<%=h @post.body %>
Better still, install the xss-shield plugin which will escape everything by default. Hopefully one day Rails will integrate this plugin and this will be less of a problem.
restful_authentication security problem
Last year there was a major security problem with restful-authentication which meant that an attacker would be able to log in without any credentials and use the first account found in the database (probably an admin one too). The plugin was subsequently patched - but it’s worth checking to see which version the site is using.
attr_accessor
I’ve saved the most common security flaw until last, not using attr_accessor and attr_protected correctly (or not using them at all).
The ActiveRecord method update_attributes is very convenient, and allows you to update your model easily with the request’s parameters. However, this can lead to some unforeseen consequences, like an attacker updating fields you weren’t expecting, like ‘is_admin’ and ‘role’.
The first thing I do when auditing, is to go to Rails schema.rb file (which incidentally I believe should always be checked into source control) and check the ‘users’ table (if there is one). A lot of sites have the ability to make a user an admin, or have different roles for users. It’s very important that those columns are attr_protected - i.e. they can’t be updated with update_attributes.
If they aren’t protected, it’s trivial for an attacker to guess the column name, add a few fields to a form, and make themselves an admin.
So there you have it, the most common security flaws in Rails applications. Can you think of any other ones?