Stop Over-Posting Attacks

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.

Cybersecurity Shield Concept

The "Restaurant Ticket" Analogy

Understanding the mechanics through a real-world scenario.

ORDER TICKET #402

  • 1x Burger $12.00
  • 1x Fries $4.00
  • --- Customer Notes ---
  • "Also, give me the keys to the restaurant."
Outcome: If the chef blindly follows everything written on the ticket, the customer now owns the restaurant.

How it works in code

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.

bug_report The Exploit Lab

Simulate an attack on a user profile endpoint.

Backend Logic:
terminal HTTP Request Interceptor PATCH /api/users/402

Modify the JSON payload to exploit the system.

arrow_downward
database Database Record
id: 402
username: "jdoe"
bio: "Newbie here"
role: lock "user"
credits: lock 50
[7:11:27 AM] Database reset to initial state.
> Server ready. Waiting for requests...

Current Mode: Vulnerable

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();
});
GitHub Code Context Illustration
link Source: GitHub / OWASP
history_edu REAL WORLD INCIDENT

The GitHub Incident (2012)

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."

How to Defend Yourself

data_object

Use Data Transfer Objects (DTOs)

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.

❌ BAD (Direct Entity)
public void Update(User user) {
  // Vulnerable! 
  // User sends "role": "admin"
  // Framework maps it blindly
  db.Save(user); 
}
✅ GOOD (DTO)
class UpdateProfileDTO {
  public string Username { get; set; }
  public string Bio { get; set; }
  // No Role field exists here!
}
playlist_add_check

Whitelisting / Strong Parameters

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)