Imagine you’re building a platform for people to share their favorite recipes. You want to make it easy for users to add their recipes, so you set up a form where they can fill in all the details, like the ingredients, cooking time and serving size.
But wait! What if a sneaky hacker comes along and adds a secret ingredient to their recipe that could harm people who eat it? This is where Mass Assignment comes in.
Mass Assignment is a common issue in API security that happens when an incoming request is automatically assigned to an object without checking each field. This can be dangerous, as it can allow attackers to manipulate your data and cause serious harm.
To protect your platform and your users, it’s important to understand Mass Assignment and how to prevent it. Don’t worry, it’s not rocket science. We’ll go through the basics and some vulnerable code examples and their prevention techniques.
Real-World Scenario
Scenario; A blog website allows users to leave comments on posts. The comments are stored in a database.
Problem; If an attacker is able to modify the HTML form used for submitting comments, they can send malicious data to the server and potentially insert malicious code into the database. This could lead to security vulnerabilities such as Cross-Site Scripting (XSS) attacks.
Here’s a step-by-step implementation of a PHP script that handles comment submissions;
Create a ‘Comment‘ class that will hold the comment data:
class Comment {
public $username;
public $content;
public function __construct($data) {
$this->username = $data['username'];
$this->content = $data['content'];
}
}
In the main PHP script, check if the request method is ‘POST‘:
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = $_POST;
$comment = new Comment($data);
...
...
...
}
Connect to the database and prepare a query for inserting the comment:
$db = new mysqli('localhost', 'username', 'password', 'comments');
$stmt = $db->prepare("INSERT INTO comments (username, content) VALUES (?, ?)");
Bind the comment data to the query parameters:
$stmt->bind_param("ss", $comment->username, $comment->content);
Execute the query:
$result = $stmt->execute();
Check if the query was successful and show a success or error message to the user:
if ($result) {
echo "Success! Your comment has been posted.";
} else {
echo "Error: Your comment could not be posted.";
}
Filter the comment content to remove potentially harmful HTML tags (Optional):
$comment->content = filter_var($comment->content, FILTER_SANITIZE_STRING);
This code is a secure implementation for handling comment submissions. It uses prepared statements to prevent SQL injection attacks and filters the comment content to remove potentially harmful HTML tags, which helps to prevent XSS attacks.
By following these steps, you can ensure that your website’s comment feature is secure and protects both the website and its users from malicious attacks.
Some Vulnerabilities of Mass Assignment
Mass assignment is a vulnerability in which an attacker can pass large amounts of data to a server including data that was not intended to be received. This can lead to several security problems including the following;
Injection Attacks
Mass assignment can also lead to injection attacks such as SQL injection or script injection. For example; if the user’s data is directly inserted into a SQL query an attacker could include malicious code that would be executed on the server.
$user = new User($_POST);
$db = new mysqli('localhost', 'username', 'password', 'users');
$query = "UPDATE users SET name='" . $user->name . "', email='" . $user->email . "' WHERE id=" . $user->id;
$db->query($query);
Unauthorized Access
Mass assignment can allow an attacker to gain access to parts of the system that they should not have access to. For example; if the user data includes a ‘role‘ attribute, an attacker could modify the form to include the role of an admin, allowing them to access restricted areas of the website.
$user = new User($_POST);
if ($user->role === "admin") {
// Show admin dashboard
} else {
// Show regular user dashboard
}
Overwrite Important Data
The attacker can overwrite data that was meant to be protected such as passwords, credit card numbers and other sensitive information. For example; if you have a form that allows users to update their profile information, an attacker could modify the form to include a new password, overwriting the user’s existing password.
$user = new User($_POST); $user->password = "new_password"; $user->update();
Data Corruption
Mass assignment can cause data to become corrupted if the received data is not validated properly. For example; if the user’s data includes a ‘birthdate‘ attribute, an attacker could modify the form to include an invalid date causing the application to break or produce unexpected results.
$user = new User($_POST); $birthdate = new DateTime($user->birthdate); $today = new DateTime(); $age = $today->diff($birthdate)->y;
Increased Attack Surface
Mass assignment increases the attack surface of an application making it easier for attackers to find and exploit vulnerabilities. For example; if the user’s data includes a ‘description‘ attribute, an attacker could modify the form to include malicious JavaScript code which would be executed when the user’s profile is viewed.
$user = new User($_POST); echo "Name: " . $user->name . "<br>"; echo "Description: " . $user->description . "<br>";
How to Fix Mass Assignment
To prevent & mitigate the dangers of mass assignment, it is important to properly validate and sanitize the data that is received from the user. Approaches that can be taken to ensure that your application is secure are;
Input Validation
Validate the data received from the user to ensure that it is safe, secure & expected. This can include checking the format of the data such as dates or numbers as well as checking that the data within a certain range.
$user = new User($_POST);
if (!filter_var($user->email, FILTER_VALIDATE_EMAIL)) {
die("Invalid email address");
}
if ($user->age < 0 || $user->age > 120) {
die("Invalid age");
}
$user->update();
Whitelist Attributes
Only allow specific attributes to be updated by the user. This can be done by manually defining a list of allowed attributes & ignoring others.
$allowed_attributes = array('name', 'email');
$user_data = array_intersect_key($_POST, array_flip($allowed_attributes));
$user = new User($user_data);
$user->update();
Sanitization
Remove any potentially_malicious characters from the data such as <script> tags. This can be done using functions such as ‘strip_tags‘ or html-special-chars.
$user = new User($_POST); $user->description = strip_tags($user->description); $user->update();
Use a Framework
Consider using a framework that includes built-in security features to help prevent mass assignment vulnerabilities. Many frameworks include features such as input validation & sanitization. As well as an ORM (Object-Relational Mapping) layer that abstracts away the database operations, making it harder to make mistakes & easier to write secure code.
For example; in Laravel, a popular PHP framework, you can use the ‘$fillable‘ property to define which attributes can be mass assigned and the ‘create‘ method to create a new instance of a model while automatically validating and sanitizing the input data:
class User extends Model
{
protected $fillable = ['name', 'email'];
}
$user = User::create(request()->all());
In this example; only the ‘name‘ and ‘email‘ attributes will be allowed to be mass assigned and any other attributes present in the input data will be ignored. Additionally, Laravel’s built-in validation features can be used to ensure that the data received from the user is safe and expected, without having to write the validation code yourself.
Prepared Statements
Use prepared statements to mitigate SQL_Injection attacks. This involves using placeholders in the SQL-Query which are then replaced with the actual data at-runtime.
$user = new User($_POST);
$db = new mysqli('localhost', 'username', 'password', 'users');
$query = "UPDATE users SET name=?, email=? WHERE id=?";
$stmt = $db->prepare($query);
$stmt->bind_param("ssi", $user->name, $user->email, $user->id);
$stmt->execute();
Summary
Mass assignment is a security vulnerability that occurs when an application allows data from an untrusted source, such as a user, to be directly assigned to an object. This can result in unintended and potentially harmful changes to the object, such as modifying sensitive data or executing malicious code. To prevent and mitigate mass assignment vulnerabilities, it is important to properly validate and sanitize the data that is received from the user, whitelist attributes that can be updated, use input validation, sanitize data, use prepared statements and consider using a framework that includes built-in security features. By following these best practices, you can ensure that your application is secure & protected against mass assignment vulnerabilities.