Several frameworks offer handy mass-assignment features to lessen the workload for developers. Because of this, programmers can directly insert a whole set of user-entered data from a form into an object or database. This feature is often used without a whitelist for protecting the fields from the user’s input. This vulnerability could be used by an attacker to steal sensitive information or destroy data.
Web mass assignment vulnerability is a type of security vulnerability where attackers can modify the model attributes of an application through the parameters sent to the server. Reversing the code, attackers can see these parameters and by assigning values to critical unprotected parameters during the HTTP request, they can edit the data of a database and change the intended functionality of an application.
Ruby on Rails is a web application framework that is vulnerable to this type of attack. The following example shows how attackers can exploit mass assignment vulnerability in Ruby on Rails. Assuming we have a User model with the following attributes:
class User < ActiveRecord::Base
attr_accessible :username, :email
end{ "user" => { "username" => "hacker", "email" => "hacker@example.com", "admin" => true } }Exploiting Mass Assignment Vulnerability
for i,j,k in cur.execute('select * from users where username=? and password=?',(username,password)):
if k:
session['user']=i
return redirect("/home",code=302)
else:
return render_template('login.html',value='Account is pending for approval')We can see that the application is checking if the value k is set. If yes, then it allows the user to log in. In the code below, we can also see that if we set the confirmed parameter during registration, then it inserts cond as True and allows us to bypass the registration checking step.
try:
if request.form['confirmed']:
cond=True
except:
cond=False
with sqlite3.connect("database.db") as con:
cur = con.cursor()
cur.execute('select * from users where username=?',(username,))
if cur.fetchone():
return render_template('index.html',value='User exists!!')
else:
cur.execute('insert into users values(?,?,?)',(username,password,cond))
con.commit()
return render_template('index.html',value='Success!!')Prevention
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:username, :email)
end
endIn the example above, the user_params method returns a new hash that includes only the username and email attributes, ignoring any more input the client may have sent. By doing this, we ensure that only explicitly permitted attributes can be changed by mass assignment.