I wanted to start using attr_accessible with my models to stop the problem with mass assignment. I understand how it works and have researched as much as I could.
What I don't understand is the difference between using update_attributes(params[:my_form]) or create(params[:my_form]) and setting the fields one by one? Aren't both just as vulnerable?
What is the difference between NOT having attr_accessible and doing this...
@model_object = ModelObject.new
@model_object.create(params[:model_object_params])
And having attr_accessible and doing this...
@model_object = ModelObject.new
@model_object.field1 = params[:model_object_params][:field1]
@model_object.field2 = params[:model_object_params][:field2]
@model_object.field3 = params[:model_object_params][:field3]
@model_object.save!
Aren't both these methods of creating the record just as vulnerable? The hacker/cracker could send a url to both these methods and both would do just the same, right?
Or does using attr_accessible and updating the fields one-by-one do something different or somehow become safer?
There's where all these methods I'm finding of using attr_accessible don't make any sense to me. It seems to be doing the same thing two different ways. What am I missing?
Thanks.
The solution 😊 Jackson provides an annotation that can be used on class level (JsonIgnoreProperties). So simple, just add @JsonIgnoreProperties(ignoreUnknown = true) before the class.
It is a severe API threat that arises when you save the request body as it is on the server instead of getting values from it one by one. It allows the user to initialize or overwrite server-side variables that the application does not intend.
In the way you are doing it, it does not prevent "mass assignment".
"Mass assignment" is the term used when Rails is handling the assigning of values to attributes in a model. This is typically done in a controller, using the names and values in params
.
When you're doing the assigning yourself, it is also "mass assignment", in a way; but you have fine control over what to assign and what not to in this case. So, to save writing that boilerplate assignment code, Rails provides attr_accesible
- same control, less code.
To see how it is used:
Presume that a ActivityLog
model has an attribute called user_ip_address
.
Now, user_ip_address
is an attribute in the model, and could be assigned by mass-assignment or by "self-rolled-mass-assignment".
But in both cases that is wrong -- you don't want user-supplied input to set a value for that attribute.
Instead, you want to always find out the actual IP address of the user and assign that value (ignoring any
value in params
). So you would exclude user_ip_address
from attr_accessible
and instead assign it yourself.
attr_accessible :all_attributes_except_user_ip_address
@al = ActivityLog.new(params[:model_object_params])
@al.user_ip_address = get_origin_user_ip_address
@al.save
For any information that a user should not be able to change, use attr_accessible
and exclude it from the list.
The short answer is that it stops field4
from being set implicitly.
The difference is that without attr_accessible
a hacker could update a field that is not in your form. With attr_accessible
this impossible.
E.g. if your user model has a field is_admin
, a hacker could try to create a new admin by posting:
params[:user][:is_admin] = true
If attr_accessible
is set (and obviously it shouldn't contain is_admin
) this is impossible.
About your example: if your model only has field1
, field2
and field3
and there are no other database columns you want to protect, there is no need to use attr_accessible
. Hope this makes it clear.
Just remember:
Without any precautions Model.new(params[:model]) allows attackers to set any database column’s value.
Source: http://guides.rubyonrails.org/security.html#mass-assignment
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With