jump to navigation

A Quick Overview of Eloquent’s (Laravel) Mass-assignment Protection May 14, 2013

Posted by Tournas Dimitrios in PHP.

Laravel’s  ORM (Eloquent) provides a beautiful , simple Active-Record implementation for working with your database . Each database table has a corresponding “Model_Class” which is used to interact with that table . As I’m aware off , many [all] ORM’s had the ability to mass-assign properties directly into the database , which is a   security vulnerability . Mass assignment is something most programmers make use of as it provides an easy (convenient) way to populate the properties of a model object from a form . Unfortunately its simplicity can make it a target for hackers , a submitted form can easily be forged just by using a CLI-tool (CURL) or by using a browser plugin (Firefox’s Firebug) to pass POST parameters to a page . The way to stop this kind of attack is by limiting the attributes that can be set from the form (or from a POST method) .

Basics first :

Active-Record is designed upon the principles of the “Active-Record” design pattern , which was first described by Martin Fowler . The Active -Record pattern has been implemented in many forms across  all  programming languages , the basic concepts remain the same though . A database table is mapped into  a Class (the Model in a MVC paradigm) , and each instance of that Class represents a table row . The tables and rows of the database are abstracted into native PHP objects . This allows the programmer to focus more on manipulating the data and less on writing SQL queries . The following lines of code are just a representation  of what I’m talking about , it’s evident that the code hides (abstracts) the database query language (SQL) .

// Get all records from Users table
$users = User::all() ;
// How many records of the Users table has been voted more than 100 times
$count = User::where('votes', '>', 100)->count();
//  Updating a record into Users table
User::where('username', '=', 'user3')->update(array('password' =>  Hash::make('John123')));

To keep things concentrated , most Frameworks apply the “Convention Over Configuration” paradigm  . In our Active Record implementation ,  a User Model Class maps to a Users Database-table (notice the plural and singular expression) . This default convention can be explicitly overwritten though .

Back on track : 

Let’s recap : a Class that implements the Active-Record design pattern is used to interact with our database-tables . All we have to do is  using CRUD operations on an Object that was previously instantiated from the aforementioned  Class  , neglecting the underlying SQL logic . And you might wonder , where is the vulnerability that we talked about at the beginning of this article  . Well let’s be honest , we’re almost always lazy programmers  and prefer to write less code (yes I’m cheating here , assuming that all programmers behave like me ) . Our laziness establishes an assured “achilles heel” into  application’s foundations . Sooner or later a “black hat guy” will discover our application’s vulnerability and most likely he will try to  occupy administrator privileges . In such a scenario , the consequences are evident , I don’t even want to think about it .
A couple years ago (early in 2012 ) , a Russian developer named Homakov , discovered the “Mass Assignment” vulnerability into Github’s website and used this “security hole”  to gain commit access . Github’s web-app was build on Rails , but as aforementioned previously , the concepts remain the same , no matter which programming language is used to implement an Active Record design pattern . Don’t fear , the flaw has since been fixed in Rail’s  and Eloquent (Laravel’s Active Record implementation) , and I’m sure that other ORMs have taken their precautions to .
Do you remember my aforementioned “Convention Over Configuration” paradigm ? This also applies into this situation , the default “set-up” in Laravel’s and Rail’s Active Record implementation is to suspend “mass assignment” functionality , it can be overwritten though .  This restriction protects our application , in case a programmer  skipped to apply basic security practices . There are situations that we don’t need this “strict security model” though ( for instance : during prototyping or development cycle of our application ) .
A practical example will illustrate what this article is trying to describe . First , the code-example shows how mass assignment was done until the restrictions were applied ( after Homakov’s discovery)  .


class UserController extends BaseController

	public function save()
		$user = new User(Input::all()) ;
		$user->save()  ;
		// Do other stuff here


In the above code , all form submitted fields were inserted into the database-table (mass assignment ) . It’s not shown here , but the code took all precautions to protect our application against SQL-injection , Cross-Site-Scripting XSS and Cross-Site-Request-Forgery CSRF . Mass assignment wasn’t restricted , an hacker had to guess how the database-table indicated an administrator / logged-in user (perhaps a column with a name of : is_loggedIn , is_admin ) . Last step of attacker’s journey was to submit a forged form which contained those column fields into the submitted data and boooom , he gained free access to the web-app .

The following code demonstrates how we could protect our app against the mass assignment vulnerability :


class UserController extends BaseController

	public function save()
		$user = new User() ;
		$user->email = Input::get('name');
		$user->pnone = Input::get('phone');
		$user->name = Input::get('name');
		$user->save()  ;
		// Do other stuff here


The code above demonstrates the right way to store submitted form data  . We allow only specific field to be stored into the database table .
As aforementioned , by default , mass assignment is disabled in Laravel , we can loosen or disable this restriction though . In Laravel 4 two properties can configure Model’s behavior ($fillable and $guarded ) .

class User extends Eloquent {
In this example , only the three listed attributes will be mass-assignable.
    protected $fillable = array('first_name', 'last_name', 'email');


class User extends Eloquent {
In the example , the id and password attributes may not be mass assigned
    protected $guarded = array('id', 'password');
Or blocking all attributes from Mass Assignment
	protected $guarded = array('*');


Happy coding .


1. Geoffrey - January 7, 2014

Thanks for this; it makes sense now.

2. Crazy Zurfer - February 5, 2014

Amazing!, didn’t understood the vulnerability at first.. now everything makes sense :D!

3. Bare - April 28, 2014

Your style is unique compared to other folks I have read
stuff from. Thanks for posting when you’ve got the opportunity, Guess I’ll just bookmark this web site.

4. Minecraft - May 20, 2014

Hi there to every body, it’s my first go to see of this website; this website includes amazing
and really fine information for visitors.

5. Budy - January 22, 2015

great example….thkas for this

Tournas Dimitrios - January 23, 2015

@Budy , you are welcome🙂

6. Sergiu - May 6, 2015

Another option would be to use
protected $guarded = array(‘id’, ‘_token’)
and in your controllers get the user data with
$request->only(‘field1’, ‘field2);
I like this approach more than specifying the $fillable fields because it gives you more freedom in your code and $fillable fields may not be the same for all users.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s