Secure your Rails apps!

It is time to secure your Rails apps! I mean it is always time to do that, but (as you might have heard) github just got hacked. So if you have a public facing Rails app you should really ask yourself “Can I be sure that our security standards are better than the ones of github?”

What happened?

A russian programmer started an argument about the mass assignment vulnerability and how Rails could provide better protection against it. However the issue got closed again and again as it was basically argued that securing the app is the responsibility of the programmer. So he took a different approach, demonstrating that the vulnerability is even present in one of the biggest and well-known Rails applications: github itself. He managed to make a commit to the Rails master branch, which turned into a lengthy discussion including some memes. He also created a ticket which appears to be from the future by abusing this vulnerability. For the sake of completeness, he informed github of the presence of these vulnerabilities first. You may also want to checkout github’s summary about the incident.

I don’t want to discuss whether his actions were right or wrong, but in the end Rails changed the default for new apps to make this vulnerability less common, which is a good thing to my mind.

What is this mass assignment vulnerability?

The mass assignment vulnerability is described pretty well in the Rails security guide – which you should absolutely read in its entirety! Basically the problem is the following:

Whenever you scaffold generate code for some resource in Rails, which is pretty common, you can see a snippet like this for creating a resource:


@user = User.new(params[:user])

What this does is create a new user, with all the attributes set to the values that got transmitted from a form and are now in the params[:user] hash. This is very concise as here you can mass assign everything the user entered: name, email, description etc. Cool right? This is why it’s not only generated but also written pretty often. Yeah so far so good.

The problem starts when you got some attributes in your model, which you don’t want your users to have direct access to. For instance the boolean admin, determining if a user is an admin or not. The attacker may use tools to manipulate the html form and hence the transmitted parameters to include the key value pair: admin: true ! So params[:user] may look like this:

params[:user] = { name: 'Evil', email: 'evil@example.com', description: 'I am an admin soon', admin: true}

And all of a sudden our newly created user is an admin and can do everything he/she wants to do – which was totally unintended by the developer! Of course this also works with updating records and not just with creating them.

This issue is actually pretty damn well-known and was also a big story during the start of the Diaspora social network (among many other vulnerabilities).

Holy sh**! What can I do to protect my app?

Well in general it is pretty easy to protect against this kind of attack you just have to add attr_accessible to all your rails models. This white lists the attributes, that can be assigned during mass assignments. Everything else can not be assigned during mass assignments. So for our example this would look like this:

class User < ActiveRecord::Base
  attr_accessible :name, :email, :description
  # rest of class omitted
end

Notice that admin is missing from the attributes after attr_accessible. That’s because we don’t want to have it mass assigned during creation/update. So now go ahead and secure your Rails applications, or stay for the pro-tip…

Pro-tip: Use Brakeman

Brakeman (can also be found on github) is a static analysis tool (fancy term for: looks at your code, doesn’t execute it), looking for vulnerabilities. So it is a vulnerability scanner for Ruby on Rails. It takes a good look at your source code and informs you of any found security vulnerabilities including the confidence of the scanner that this is indeed a problem (e.g. not a false positive). It seems to find mass assignment vulnerabilities very reliably and it also informed me of a possible Cross-site scripting (XSS) vulnerability in my Rails version (3.2.0) and recommended an update to 3.2.2, as this version fixes the problem. So it is also pretty up to date and I can only recommend it. Now go ahead and gem install brakeman or add it to your Gemfile.

However the default output isn’t very beautiful on my system and hides many important parts so I’d recommend you to run:

brakeman -f html -o brakeman.html path/to/app

For a bit prettier html output. Hope that this helps. And don’t forget to add this brakeman.html to your gitignore. Oh by the way: they also have a plugin for Jenkins/Hudson.

So now go ahead and make your Rails apps more secure!

One thought on “Secure your Rails apps!

Leave a comment