Mass Assignment in Ruby
Vulnerable Example
Rails >= 4
In Rails 4 and newer, protection against mass assignment is on by default. The Action Controller Parameters must be used to choose which attributes should be permitted for mass updating by using the permit
method.
A vulnerable example would explicitly permit an unsafe attribute, such as is_admin
.
def signup
@user = User.new(params.permit(:name, :password, :first_name, :last_name, :is_admin))
end
An attacker could craft a request by adding the is_admin
POST field with value 1
to exploit the attack and register a new user with administrative privileges.
It’s possible to change this safe default by either setting the permit_all_parameters
to modify all new instances or by updating a single instance by invoking the permit declaration with .permit!
.
User.new(params.permit!)
Rails < 4
In previous versions, the mass assignment feature may allow an attacker to set any model’s attributes. The following Ruby snippet shows a Ruby On Rails controller that creates a new user based on the user-provided user
object.
def signup
@user = User.new(params[:user])
end
Prevention
Rails >= 4
Make sure to only permit values that are safe to be set. Foreign keys are likely unsafe, as they may allow an attacker to manipulate foreign records.
Rails < 4
Old versions of Ruby On Rails should use the attr_protected
method, which takes a list of attributes that will not be accessible for mass assignment. For example:
attr_protected :is_admin
The attr_accessible
method can also be used to enforce an allow list approach. It takes a list of attributes that will be accessible, while all other attributes will be protected.
attr_accessible :name, :password, :first_name, :last_name
References
Ruby On Rails Security Guide - Mass Assignment
Ruby On Rails Guides - Action Controller Overview - Strong Parameters
CWE - CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes