Mass assignment is a common method of storing form data in rails. Unfortunately, its simplicity has become the target of hacker attacks. The following explains why and how to solve the problem.
The preceding form is a simple registry form. When you enter name and click Submit, a new user is created. The user model is defined as follows:
rubycreate_table :users do |t| t.string :name t.boolean :admin, :default => false, :null => falseend
When a user clicks submit, the following action is executed:
rubydef create @user = User.new(params[:user]) if @user.save flash[:notice] = "Successfully registered" redirect_to :action => ’show’, :id => @user.id else render :action => :new endend
The Params you pass in are created. As discussed earlier, the content in Params cannot be fully trusted. The following shows how hacker registers itself as admin.
Attack website
The following curl command line is used to post parameters to the page.
Terminal
curl -d "user[name]=hacker&user[admin]=1" http://localhost:3000/Users/
The command above sends the command named 'hacker' and Admin. The command line is as follows:
Terminal
Processing UsersController#create (for 127.0.0.1 at 2009-02-03 20:18:54) [POST] Session ID: 8daeaad6eb382c903e595e704b626ef7 Parameters: {"user"=>{"name"=>"hacker", "admin"=>"1"}, "action"=>"create", "controller"=>"users"} SQL (0.000390) INSERT INTO users ("name", "admin") VALUES(’hacker’, ’t’)Redirected to http://localhost:3000/users/show/2
Hackers can do this mainly because mass assignment: we use the Params parameter to create a user, and the parameters passed by the hacker are consistent.
Protection attributes
The method to prevent such attacks is to restrict the storage of data from forms. Rails hasattr_protected
The attribute of the method defined by the method cannot be set through mass assignment.
Ruby
class User < ActiveRecord::Base has_many :comments attr_protected :adminend
In the user model, set the admin attributeattr_protected
.
Now, if you resend the preceding curl, you will see the following log information. Even if the admin value in Params hash is true, the admin attribute is not saved as true.
terminalProcessing UsersController#create (for 127.0.0.1 at 2009-02-03 20:37:49) [POST] Session ID: 381cee077c1367bf0cc410a2259adb96 Parameters: {"user"=>{"name"=>"hacker", "admin"=>"1"}, "action"=>"create", "controller"=>"users"} SQL (0.000327) INSERT INTO users ("name", "admin") VALUES(’hacker’, ’f’)Redirected to http://localhost:3000/users/show/5
The admin attribute is set to false.
The website still has vulnerabilities. In applications, many models have relationships. For example, if one user has many comments, has_events provides a method to set comment_ids through mass assignment. Use the following command to attack comment IDs.
rubycurl -d "user[name]=hacker&user[admin]=1&user[comment_ids][]=1&user[comment_ids]=2"http://localhost:3000/users/create
has_many
So that the user model hascomment_ids
= [], The above command is used to attack commend_ids = [1, 2]. The following log shows comments owned by hacker users.
terminalProcessing UsersController#create (for 127.0.0.1 at 2009-02-04 20:27:36) [POST]Session ID: e6bee21260899c7dce47bc5040dcd467Parameters: {"user"=>{"name"=>"hacker", "comment_ids"=>["1", "2"], "admin"=>"1"}, "action"=>"create", "controller"=>"users"}Comment Load (0.001) SELECT * FROM comments WHERE (comments."id" IN (1,2)) SQL (0.001) INSERT INTO users ("name", "admin") VALUES(’hacker’, ’f’) Comment Update (0.000094) UPDATE comments SET "title" = ’Comment 1’, "user_id" = 8 WHERE "id" = 1 Comment Update (0.000071) UPDATE comments SET "title" = ’Comment 2’, "user_id" = 8 WHERE "id" = 2
To solve the above problem, it is best to use it in the model.attr_accessible
Replaceattr_protected
.attr_accessible
Lists the attributes that can be set through mass assignment in the model.
The face definition of the update mode is as follows. Only the name attribute can be set through mass assignment.
Ruby
class User < ActiveRecord::Base has_many :comments attr_accessible :nameend
Finally, the log is as follows:
Ruby
Processing UsersController#create (for 127.0.0.1 at 2009-02-04 20:39:15) [POST] Session ID: 48b9264e8da94d0a0edadce5e31ac500 Parameters: {"user"=>{"name"=>"hacker", "comment_ids"=>["1", "2"], "admin"=>"1"}, "action"=>"create", "controller"=>"users"} SQL (0.000307) INSERT INTO users ("name", "admin") VALUES(’hacker’, ’f’)Redirected to http://localhost:3000/users/show/9
Http://railscasts.com/episodes/26-hackers-love-mass-assignment? View = asciicast
Railscast26 Hackers love mass assignment security risks in creating and updating models by Params in rails