Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ruby on Rails: Secure Mass Assignment (stephensclafani.com)
24 points by ssclafani on Jan 4, 2010 | hide | past | favorite | 15 comments


    # config/initializers/disable_mass_assignment.rb
    ActiveRecord::Base.send(:attr_accessible, nil)

    # app/models/some_model.rb
    class SomeModel < ActiveRecord::Base
      attr_accessible :whitelisted, :attributes
    end


This post is nothing new but it's worth reading if you're a Rails dev because it highlights a uniquely Railsy security flaw, which is the default-allow accessibility of model attributes, which is made worse by the fact that ActiveRecord hides the schema (and therefore the attribute file) from the class definition where you override accessibility.

By default, all attributes should have been inaccessible to ActiveRecord::Base#new and ActiveRecord::Base#update. That was a design-level mistake.


Mass assignment is a problem that is not unique to Rails. People can and do write software that offer this feature. Last seen by me in some php code in production since 2003.. of course without a way to white/blacklist attributes. :)


Is it really Rails specific? I seem to remember Struts working the same way and most other reflection based frameworks working the same way.

The particular solution outlined in the OP is quite incomplete. We need a check not see just which attributes can be edited by a user, but which rows can be edited by a user. attr_accessible offers no protection there.


It's not Rails-specific that you need to protect your models with reasonable security logic. This particular flavor of "oops, not protected by default" is Rails-specific.

And Rails is highlighting the fact that "allowed by default" is convenient, while the post highlights the fact that "allowed by default" is insecure :-)


"This particular flavor of "oops, not protected by default" is Rails-specific."

Uhh...if it is in most other frameworks, as I claim, and you don't deny, then it is not Rails-specific.


When I say "this particular flavor of", I use that to distinguish between Rails and other frameworks. The protected attribute tags that Rails uses are not common to other frameworks.


Well said. I blogged about this same thing about 3 years ago (http://web.elctech.com/2007/03/01/securing-your-models/). It's amazing how many application I come across that don't protect their attributes.



The black box test really drives home the point that this is a very discoverable and exploitable issue when not handled correctly.


I've often felt for us at least that any "belongs_to" relationship should get pulled out of mass assignment by default. 95% of the time I imagine in the world, a belongs_to field on a child record is not going to want to be updated by some mass assignment, but is assigned instead by instantiation parent.children.new or manual assignment. Child.new(:parent=>parent)

Would this be a valid change to Rails. All belongs_to attributes are by default not accessible to mass assignment?


Also checkout this screencast by Railcasts. It may show you how the vulnerability can be exploited a bit more clearly to those of you who are possibly thinking "how the hell can they pass more parameters than the ones I have in my form".

http://railscasts.com/episodes/26-hackers-love-mass-assignme...


attr_protected / attr_accessible is the lamest workaround in rails. Tons of overhead and potential bugs just so you can have a one line controller.

Better idea: just set the attributes you want explicitly in the controller. Then your forms will never set data that you don't want it to.


I haven't used it, but a quick Google search turns up this plugin, to require whitelisting mass-assignable attributes:

http://github.com/ryanb/trusted-params

That should fix this problem for apps that use the plugin.


In a related vein, I wrote http://github.com/mhartl/find_mass_assignment to find likely mass assignment vulnerabilities in Rails apps.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: