Also known as Mass Assignment. A vulnerability where attackers modify database fields they shouldn't access—like isAdmin or balance—by injecting extra properties into web requests.
Understanding the mechanics through a real-world scenario.
Web frameworks often have features that automatically take data from a request (like a form or JSON) and "bind" it to a database object to save time.
If a developer simply says "Save whatever the user sent" without filtering, an attacker can send extra fields (like role: "admin") that the interface didn't show, but the database will happily accept.
Simulate an attack on a user profile endpoint.
Modify the JSON payload to exploit the system.
The backend blindly merges incoming JSON into the database object using a method like Object.assign() or unconfigured AutoMapper. Security checks are bypassed.
// VULNERABLE
app.patch('/users/:id', (req, res) => {
let user = db.get(req.params.id);
// ❌ Blindly merges everything
Object.assign(user, req.body);
user.save();
});
In March 2012, a developer named Egor Homakov discovered he could update the timestamp on a comment by injecting a field. When he wasn't taken seriously, he escalated.
He realized the main "Public Key Update" form was vulnerable to Mass Assignment. He injected his own public SSH key into the Rails organization's project settings, effectively gaining commit access to the Ruby on Rails framework itself.
"He committed a file to the Rails repository just to prove he could. It changed the way the entire industry looks at default-allow binding."
The Gold Standard.
Never bind your internal database entity directly to the request. Create a specific class that only contains the fields you want to allow.
public void Update(User user) {
// Vulnerable!
// User sends "role": "admin"
// Framework maps it blindly
db.Save(user);
}
class UpdateProfileDTO {
public string Username { get; set; }
public string Bio { get; set; }
// No Role field exists here!
}
Common in Rails and dynamic languages.
Explicitly tell the framework which fields are allowed. Any other fields are silently ignored or raise an error.
// Ruby on Rails Example
def user_params
# Only allow these specific fields
params.require(:user).permit(:username, :bio)
end
# Even if they send :role, it's filtered out here
User.update(user_params)