Mass Assignment
1. Introduction:
Modern frameworks encourage developers to use functions that automatically bind input from the client into code variables and internal objects. (Easier to code !-> safe code) The binding of client-provided data (e.g., JSON) to data models, without adequate properties filtering based on an allowlist, usually leads to Mass Assignment. Either through guessing objects properties(eg. admin: true
, role: admin
), exploring other API endpoints, reading the documentation, or providing additional object properties in request payloads, allows attackers to modify object properties they are not supposed to.
You can read more about Mass Assignment, from an attacker's perspective, here.
2. Typical vulnerable code:
In the usual vulnerable scenario, the developer does not bind what aspect of the object they want to update through the request. Take a look at the following code:
And now assume that the request would look similar to this:
Since the developer does not specifically bind which fields of the accounts they want to update, it follows suit that we can input ANY field(as long as we know/ guess them) and hence update all those fields. With the request of:
An attacker successfully updates their role
field into admin
, thus escalating their privileges.
This is just a typical attack scenario, and one can infer that there are several other ways of exploiting this vulnerability(eg. changing another user's password/ email/ username/ etc)
3. Mitigations:
By far the safest method of protecting against such a vulnerability is using a schema database validation framework(such as mongoose). You can also specifically retrieve the object that you want from the request(eg. req.body.password
) and have a function that would ONLY update the password
field. Here's how to patch the code:
Note that on line 23
we specify which exact field of the user object we want to update.
4. Takeaways:
Following these essential points will defend your endpoints against Mass Assignment:
Bind the fields that you want to work with from the request.
Do not blindly trust the methods of the frameworks you are working with. Read the documentation!
All schemas and types that are expected in the requests should be explicitly defined at design time and enforced at runtime.
You can find more details about this topic here
Last updated