What is a Mass Assignment vulnerability?

To make things easier for developers, many frameworks include features that automatically associate the parameters of an HTTP request with variables linked to an object in the application code.

A Mass Assignment vulnerability occurs when the server does not correctly filter the data transmitted by the user and associates it directly with an object without verification.

In this way, an attacker can add new parameters to the HTTP request, which will create or replace variables in the application code although this was not initially intended.

Depending on the framework, these are also known as “autobinding” or “object injection” vulnerabilities.

Impact of a Mass Assignment vulnerability

The main impact of a Mass Assignment vulnerability is linked to modifying or creating variables. Depending on the variables or objects affected, the impact can be more or less significant, ranging from the simple modification of a value with no impact to a privilege escalation.

Indeed, when the vulnerability is present in a feature linked to the creation or modification of users, it is not uncommon to be able to escalate privileges.

This was the case, for example, on the Github platform in 2012, when a Mass Assignment vulnerability enabled users to upload their SSH public key to any organisation, potentially resulting in a massive data leak.

Such a vulnerability is not to be taken lightly, as it can have a severe impact.

How to identify this type of vulnerability?

As an attacker or pentester does not necessarily have a list of all the variables and values associated with the modified object on the server side, identifying a Mass Assignment vulnerability can be complex.

Depending on the technical conditions of the pentest, here are a few ways of identifying this type of security flaw:

  • In white box, i.e. with access to the source code, it is possible to refer to the data models to identify sensitive fields that would not be transmitted by default in HTTP requests.
  • Without access to the source code, this is more complex. One technique is to test known or probable parameters. This involves fuzzing the parameters. For example, adding a “role” field to the user creation request with standard values such as “admin” or “root” can lead to a privilege escalation in the event of Mass Assignment.
  • In some cases, using the API documentation, it is possible to identify parameters that are not used by default. For example, with access to the introspection of a GraphQL API, i.e. to the list of fields associated with an entity, it is possible to try to add a variable in certain queries or mutations in the hope that this will be taken into account.
  • Another technique is to observe the server responses. If additional fields are returned, it may be useful to reuse them in requests to detect Mass Assignment. Let’s imagine, for example, that we have access to the list of users. If you access the API route used to list users, you can see a “role” field associated with each user in the server response. It may therefore be useful to add this role parameter with a valid value in the request used to modify the profile information or the request used to create a user.

What are the common exploits of Mass Assignment vulnerabilities?

Mass Assignment and privilege escalation

During a grey box pentest, we had access to an application with several levels of user privileges. We had a user access (not admin), but which nevertheless allowed us to create other users with the same level of privileges.

Using the graphic interface, the request to add a user looked like this:

The content of the server response in JSON was as follows:

As we can see, a “Profiles” field is returned in the JSON object corresponding to the new user we have just created. It seems to correspond to the user’s rights. This field has been added automatically. In particular, we can see that the newly created user has a profile of type “customer” associated with ID 5. This profile has certain roles.

The fact that this “Profiles” field is present in the response even though it was not initially filled in should immediately alert us. We can now try to replay the creation of a user by adding a “Profiles” field.

Here, we know that profile ID 5 corresponds to a “customer” type user. Let’s try this with ID 1. We’ve left the other fields empty because we didn’t know the existing values:

Server response:

The Mass Assignment attack has been taken into account. The profile ID “1” has been associated with the user we have just created. The response tells us that we have successfully created an administrator type user.

This means that on the server side, the entire JSON object sent by the attacker is used to link the transmitted fields to the user object created. This is done without checking what data is being transmitted and by accepting an unexpected field.

We can now connect with the new user. Our privileges have been escalated and we can perform all the actions restricted to administrators.

Mass Assignment on a GraphQL API and privilege escalation

During a pentest on an application running with a GraphQL API, a mutation was used to update the user’s profile. By default and using the graphical interface, the mutation transmitted was as follows:

At first glance, there’s nothing particularly interesting about this mutation. It allows a user to change his/her surname, first name and telephone number.

However, we had access to GraphQL introspection (the equivalent of the documentation for a classic API) and we were able to see that the GraphQL “User” object also had a “role” field.

By modifying the previous mutation, we were able to change the role of our user due to a Mass Assignment. This enabled us to escalate our privileges:

Full request:

Following this request, our user became an administrator because the mutation took into account the role field even though it was not sent by default.

How to prevent Mass Assignment vulnerabilities?

Fortunately, preventing or correcting this type of vulnerability is fairly straightforward.

It involves setting up a white list of fields that are authorised to be used on the server side to create or modify an object. In addition, only non-sensitive fields should be authorised. And if other fields are present in the request received, they must not be taken into account by the server.

Frameworks often allow this type of whitelist to be configured simply. A list of potential existing solutions by framework can be found on the OWASP website.

If we go back to the previous examples, in the first case, the white list must not include the “profiles” field. If a user tries to send a value for this field, the value transmitted should not be taken into account when creating the user.

In the second case, the mutation used to modify the profile must not accept the “role” value. It must be limited to the “first_name”, “last_name” and “language” parameters only.

Author : Yoan MONTOYA – Pentester @Vaadata