The APIs (Application Programmable Interfaces) are widely used to power applications, and one of the popular choices for implementing API is REST APIs. With this increase in popularity and usage, many security risks also come into the picture.
APIs have their own OWASP API Top 10 list, which describes the vulnerabilities commonly found in the APIs, including Mass Assignment.
This blog will dive deeply into understanding and exploiting mass assignment vulnerabilities.
Mass Assignment - A 20ft Overview:
Modern frameworks allow developers a convenient mass assignment functionality that lets developers directly take a “user-supplied Key-Value Pair” input to the object database. This reduces the requirement of writing code for such custom Key-Value pairs and increases the development efficiency but at the cost of security risks if not implemented correctly.
A mass assignment without a whitelist of allowed “Key-Value Pairs” could allow an attacker to use arbitrary values to create or update the resources abusing the applications’ regular workflow. Privilege escalation is one of the most common vulnerabilities arising from Mass Assignment vulnerability.
According to OWASP this vulnerability depends on the language/framework in question can have several alternative names:
-
Mass Assignment: Ruby on Rails, NodeJS.
-
Autobinding: Spring MVC, ASP NET MVC.
-
Object injection: PHP.
For example, consider an API that allows users to update their profile information. The API may accept a JSON payload that contains multiple fields such as name, email, and address. Without proper validation, an attacker can add additional fields such as "isAdmin":true” or "isSuperUser":true and gain elevated privileges as an admin or superuser.
Let’s understand this attack further with the help of a vulnerable code snippet as described below:
const express = require('express');
const app = express();
app.post('/users', (req, res) => {
const newUser = {
username: req.body.username,
password: req.body.password,
isAdmin: req.body.isAdmin
};
// Save new user to database
});
app.listen(3000, () => {
console.log('Server started on port 3000');
});
In the above code, the “newUser” object is created from the request body without validation or filtering. An attacker can attempt to craft a request with an additional field named “isAdmin”:true and send it to the server to escalate the privileges.
To remotely exploit this issue, an attacker can send a POST request with an additional "isAdmin" field set to "true" to register as an administrator. In this case, isAdmin is an optional body parameter.
POST /users HTTP/1.1
Host: example.com
Content-Type: application/json
{
"username": "attacker",
"password": "password",
"isAdmin": true
}
Now, to mitigate this issue, simply adding a check to ensure that only the user with an admin session can trigger this parameter will fix the underlying vulnerability as described in below code:
const express = require('express');
const app = express();
Const port = 3000;
app.post('/users', (req, res) => {
const newUser = {
username: req.body.username,
password: req.body.password
};
if (req.user.isAdmin && req.body.isAdmin) {
// Only admins can set isAdmin field
newUser.isAdmin = req.body.isAdmin;
}
// Save new user to database
});
app.listen(port, () => {
console.log(`Server started on port {port}`);
});
Hunting for Mass Assignment Attack in the Wild - A Practical Approach
Mass Assignment is not necessarily to be found in the user profile to perform privilege escalations. You can find it on any API endpoint, which could be using a parameter of interest to the attacker, causing significant damage to the application and its user’s reputation.
Note: Always read the API documentation to understand and identify interesting parameters/key-value pairs that could cause significant impact.
Let’s understand how to approach the Mass Assignment Attack in a black-box/grey-box assessment with the help of the “crAPI” Demo Lab.
-
Locally set up the crAPI demo lab.
-
Navigate to the shop - http://127.0.0.1:8888/shop
-
Note that the Available Balance by default is $100, and now Buy any item while capturing the request in Burp Suite or another proxy tool.
-
Send the Request to the repeater for later use.
-
Observe after purchasing the items; Available Balance is changed.
-
In the repeater tab, modify the request by changing the request method to GET and adding “/all” route to retrieve the information of all orders.
-
Observe that the application has returned all information about past orders.
-
Modify the request, and change the “all” to any random order ID.
-
Send the request, and observe the methods allowed and the order status.
-
Again, modify the request by changing the request method to PUT and adding the status as a return.
-
Send the request and observe the error message in the response.
-
Send the request again by adding the status as returned and observing that the order status has changed to returned.
-
Navigate to the shop, and observe that credit transfers to the account.
In the above lab scenario, as an attacker, it was possible to mark a delivered item as returned to get the cashback allowing an attacker to financially abuse the application with the help of a mass assignment attack.
Since now you know what chaos this attack can bring to the organization from the user integrity and the financial aspects, it is essential to understand how to implement a fix to prevent such attacks.
Fixing Mass Assignment - Remediation Approach
Some common ways to fix mass assignment issues include:
- Disable Automatic Property Mapping: Ensure that your applications have the automatic mapping disabled and always map the properties manually.
- Read-Only Key-Value Pairs: Ensure to set the fields retrieved from the “request body” that is not present in the “request body” should be read-only, and a user should not be allowed to tamper them.
You can find a detailed remediation guide here.