Chad Moran

Software Engineer for Amazon in Seattle, WA

Mass assignment vulnerability isn't just for Rails

By vulnerability I mean “vulnerability”. Its about as much a vulnerability as leaving your door unlocked is.

In case you haven’t been keeping up with recent news there was a recent shit storm over a security issue that Egor Homakov recently took advantage of. It involved him leveraging a feature of Rails called mass-assignment. This allows you to take parameters from a form or url and use them to update your model.

def update
  @user = User.find params[:id]

  @user.update_attributes params[:user]
end

This seems innocent enough - we’re just updating some properties for the user. However, this means we can update any attribute on the user, not just the ones in the form. This means we could use Firebug or the WebKit Inspector to change the name of an existing field or create a new one and submit that value. Assuming we had a boolean value named admin on the User model we could create some HTML like so.

<input type="checkbox" name="user[admin]" checked="checked" />

Then submit this with the normal form and voila! We’ve just made ourselves an admin on your site. This might seem like a huge issue that’s worth flying off the rails (get it?) to complain about and plenty of people have. However, this would be like driving your car off a bridge and saying the car is shit because it didn’t stop you from doing something stupid. We can only protect ourselves so much.

There’s an easy way to stop this from happening.

class User < ActiveRecord::Base
  attr_accessible :name
end

Now only the name field can be set using mass-assignment. This is a way to white list properties and allow the ones you want to be set. Now since we’re programmers and we like to framework the shit out of everything and absolutely hate change. Some of you might be wondering “What if I add a new field?”. Well… then update the model. If you’re willing to sacrifice security over laziness then no one can help you. There is however an option for those out there that want to blacklist properties using attr_protected. Again, if you add a new field that you don’t want being set and you forget to update your model you’re vulnerable to attack.

This feature for protecting your model is not a new or unknown feature. It has been covered before.

Now that I have that off my chest. I’d like to turn my attention to the same exact issue that exists in ASP.NET MVC – model binding.

You’ve probably used something like this in the past

public ActionResult Update(User user)
{
    // some magic DB stuff here
}

The exact same HTML I posted above could be used here to abuse the same issue. This also a known issue and has been documented about how to fix.

If you’re using UpdateModel.

this.UpdateModel(user, "Name");

… or the bind attribute …

public ActionResult(Bind[(Include = "Name")]User user)
{
}

Again, this isn’t just an issue for Rails. This problem exists in most modern web frameworks today.

The matter of the fact is you shouldn’t blame the technology for your, or others mistakes. Yes, the technology could help you however it can’t do everything. Don’t blame the car because you drove it off a bridge.

With the scope of this issue I hope it will make it more prevalent in learning materials for developers. Even those experienced can sometimes forget these issues exist.