Avoiding a mass assignment security flaw while assigning user roles

13 views
Skip to first unread message

Mohamad El-Husseini

unread,
Apr 29, 2012, 4:48:12 PM4/29/12
to rubyonra...@googlegroups.com
I have User, Account, and Role models. Role stores the relationship type between Account and User.

I know that attr_accessible should be blank in the Role model to prevent attackers from changing either the role type (owner, admin, moderator, subscriber), account, or user ids.

But what if an admin wants to change a subscriber to a moderator? This would raise a mass assignment security exception:

user = User.find(params[:id])
role = user.roles.find_by_account_id(params[:account_id])
role.type = "admin"

How do I solve this? One way is to create a separate model to represent each role (owner, admin, moderator, subscriber) and use an STI type pattern. This lets me do:

user = User.find(params[:id])
user.moderatorship.build(account_id: params([:account_id])

Tedious! I would have to create Onwership, Moderatorship, Subscribership, etc..., and have them inherit from Role. If I want to stick to a single Role model, how can I modify a role type without a having a mass assignment security flaw?

Also, I would appreciate an answer to this: Should I use a User has_many roles (user can have a single record for each role type) or has_one role (user can only have one role record, which must be toggled if their role changes) pattern?

Models:

class User < ActiveRecord::Base
  attr_accessible :name, :email

  has_many :accounts, through: roles
end

class Account < ActiveRecord::Base
  attr_accessible :title

  belongs_to :user
end

class Role < ActiveRecord::Base
  attr_accessible
end

Mohamad El-Husseini

unread,
Apr 29, 2012, 8:41:39 PM4/29/12
to rubyonra...@googlegroups.com
After doing my own research, it looks like I can approach this two ways:

1. Episode 237, Railscasts, Dynamic att_accessible, overriding mass_assignment_authorizer
2. I can use attr_accessible role, as: :admin

I would appreciate it if anyone can elaborate on the merits of either approach.

Frederick Cheung

unread,
Apr 30, 2012, 2:12:32 AM4/30/12
to Ruby on Rails: Talk


On Apr 29, 9:48 pm, Mohamad El-Husseini <husseini....@gmail.com>
wrote:
> I have User, Account, and Role models. Role stores the relationship type
> between Account and User.
>
> I know that *attr_accessible* should be blank in the Role model to prevent
> attackers from changing either the role type (owner,
> admin, moderator, subscriber), account, or user ids.
>
> But what if an admin wants to change a subscriber to a moderator? This
> would raise a mass assignment security exception:
>
> user = User.find(params[:id])
> role = user.roles.find_by_account_id(params[:account_id])
> role.type = "admin"

No it wouldn't. You can always to foo.bar = 'baz', whether or not the
bar attribute is accessible or not. What attr_accessible controls is
what would happen if you did

role.update_attributes(params[:role])

Fred
Reply all
Reply to author
Forward
0 new messages