Input and modification securely in Laravel and the Mass-Assignment problem
Laravel Framework |
an introduction
Laravel provides easy ways to work with databases using Eloquent ORM,
so that tables are represented in it in the form of Models and it becomes very easy to deal with it using some ready-made methods.
Update), and Laravel provides easy ways to do this. Just to be clear,
in this lesson, we will assume a Model named User, with the following properties:
- id is the primary key
- name
- password
- bio: a short description of the user, it is an optional value (we won't force the user to enter it) but it doesn't accept null, its default value is string empty ' '
- is_admin is true if the user is an admin
Laravel Code 1 :
$user = new User();
$user->name = $request['name'];
$user->email = $request['email'];
$user->password = bcrypt($request['password']);
// bcrypt It is a helper function that does the password hashing
if( $request->has('bio') )
$user->bio = $request['bio'];
$user->save();
We set the name, email and password and fetched their values from the Request,
as is the case for bio, but since bio is optional, the user may not enter it, so we set the condition to check its existence,
if we do not set the condition and the user does not enter it,
the value will be entered null, and the property does not accept This value is as we previously agreed.
Then we stored the new Instance from the User model in the database, and the method is similar to modification.
For example, to modify the name, we will write the following code (assuming that we fetch the user and put it in the $user variable):
Laravel Code 2 :
$user->name = $request['name'];
$user->save();
The problem with this method of creation and modification is that you need to write a long code if there are many columns in the users table,
so Laravel provides an easier way to enter all the properties at once, which is known as ( Mass Assignment ),
in the following code is an example of the creation and modification method:
Laravel Code 3 :
// construction
$user = User::create($request->all())
// modification
$user->fill($request->all())
Only this simple can be created and modified without having to set each property alone,
the method create and method fill receives an array (array) in which the key is the name of the column,
and the value is the value to be set.
Mostly, when you use the Mass Assignment method,
it will not work for you and you will get the MassAssignmentException error, why is that?
This error appears for security reasons.
Mass Assignment is a bit dangerous if you use it incorrectly.
Therefore, Laravel takes some security measures and methods to prevent the gap caused by Mass Assignment,
and this Exception appears to you if you do not take the appropriate preventive measures,
but before talking about Preventive measures, we must clearly understand the vulnerability so that we can protect ourselves from it.
What is the problem with Mass Assignment in Laravel
In the previous example, we passed all the contents of the Request to the create and fill function,
and this has several benefits, including not having to write, modify or create all the values manually,
as well as getting rid of the conditions that verify the entry of default values,
such as the condition we set for the bio property,
in the form By default, if the Request does not contain bio it will not be present in the passed array and we will get rid of this problem
HTTP Request
But entering all the contents of the Request leads to a big problem, as you know,
you can create an Http Request through some tools, or by manipulating the form in the HTML in the browser,
so I can, for example, enter your site, and manipulate the Request to modify the value of the id, for example.
, and I suppose I don't have permissions to do that,
or I can manipulate the Request and send true to the is_admin key even though you didn't originally put it in the form, this will enable me to get admin rights on the site .
For example, this is a tool that enables me to create an Http Request. Note how I can specify the fields I need, including is_admin:
Of course, this Request will not work on Laravel because Laravel provides an easy way to protect fields that you don't want anyone to manipulate or modify,
and this method is enabled by default, but it needs some modification according to your user properties,
so you will get the MassAssignmentException error if you don't What is necessary to protect the Request from tampering.
Solve the problem
If you open the User Model that comes with Laravel, you will find an array called $fillable with some properties:
Note the comment preceding the array "The attributes that are mass assignable",
meaning that the properties whose names are inside the array are the properties ,
that are allowed to be set using the methods that enter data collectively (create and fill).
password, the Request will work without problems and the addition or modification will be done using create or fill without facing any problem,
but if the request contains the previous properties in addition to,
for example, bio or is_admin, you will get a MassAssignmentException problem because bio and is_admin are not present in the fillable array .
use Laravel Mass Assignment Method
So if you want to use Mass Assignment Method as create or fill,you have to add any element you want to be modifiable to the fillable array
. Delete the array and use the $guarded array instead.
It does the same work, but in reverse.
Instead of putting the properties that you want to be adjustable, you put the properties you want to be protected and unmodifiable.
For example, one of the two arrays can be used as follows on our previous example:
Laravel Code 4 :
protected $fillable = [
'name', 'email', 'bio', 'password'
];
// or
protected $guarded = [
'is_admin', 'id'
];
* Warning: do not use $fillable and $guarded at the same time, use only one.
As you can see, this way it is safe to use Mass Assignment without fear of tampering with the Request,
so if someone tampers with the Request and tries to modify is_admin for example,
they will get a MassAssignmentException and the modification will not be done.
But before we conclude, a simple question may come to your mind, if we put is_admin in the $guarded array, we will never be able to modify it?
You can even modify these values, but not by using create or fill, but by using the first method to modify, but you can use fill,
with the first method easily to allow for example the admin of the site to modify is_admin, and prevent other members from modifying it, see this example:
Laravel Code 5 :
$user->fill($request->except('is_admin'));
if(Auth::user()->is_admin && $request->has('is_admin')) {
$user->is_admin = $request['admin'];
$user->save();
}
Note that in this example we used the two methods simultaneously, first we filled all the contents of the request except is_admin, then we used the first method to modify but after verifying that the currently registered user (who is modifying) has Admin rights, in addition to the presence of is_admin in The request.
But if I log in to your site (and I am not an admin) and try to manipulate the request and try to modify is_admin,
the first condition will prevent me, but if I try to manipulate it to modify my ID,
for example, the modification will not be done and I will receive a MassAssignmentException error.
Read also :
Comments
Post a Comment