Mass assignment occurs when a framework automatically binds user-controlled input to objects that are directly persisted to a database backend. If the application does not restrict which fields are writable, an attacker can inject additional properties into a request to overwrite sensitive data—such as authorization levels, ownership, or workflow states. This lack of filtering allows internal server-managed properties to be externally modified through a single, unfiltered write operation.
Because the application does not enforce which fields are writable, an attacker can craft a request containing any document property, including those that are meant to be managed exclusively by the server. Fields controlling authorization, ownership, workflow state, or internal identifiers all become externally settable through a single unfiltered write operation.
Attackers could forge malicious HTTP requests that will alter unexpected properties of persistent objects. This can lead to unauthorized modifications of the entity’s state. This is known as a mass assignment attack.
Depending on the affected objects and properties, the consequences can vary.
If the affected object is used to store the client’s identity or permissions, the attacker could alter it to change their entitlement on the application. This can lead to horizontal or vertical privilege escalation.
Because persistent objects are modified directly without prior logic, attackers could exploit this issue to bypass security measures otherwise enforced by the application. For example, an attacker might be able to change their e-mail address to an invalid one by directly setting it without going through the application’s email validation process.
The same could also apply to passwords that attackers could change without complexity validation or knowledge of their current value.
The following code is vulnerable to a mass assignment attack because it allows modifying the User persistent entities thanks to
maliciously forged Wish object properties.
import javax.persistence.Entity;
@Entity
public class Wish {
Long productId;
Long quantity;
Client client;
}
@Entity
public class Client {
String clientId;
String name;
String password;
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PurchaseOrderController {
@RequestMapping(path = "/saveForLater", method = RequestMethod.POST)
public String saveForLater(Wish wish) { // Noncompliant
session.save(wish);
}
}
public class WishDTO {
Long productId;
Long quantity;
Long clientId;
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PurchaseOrderController {
@RequestMapping(path = "/saveForLater", method = RequestMethod.POST)
public String saveForLater(WishDTO wish) {
Wish persistentWish = new Wish();
persistentWish.productId = wish.productId
persistentWish.quantity = wish.quantity
persistentWish.client = getClientById(with.clientId)
session.save(persistentWish);
}
}
The compliant code implements a Data Transfer Object (DTO) layer. Instead of accepting a persistent Wish entity as a parameter, the
vulnerable method accepts a WishDTO object with a safe, minimal set of properties. It then instantiates a persistent entity and
initializes it based on the DTO properties' values. The resulting object can safely be persisted in the database.
OWASP O2 Platform Blog - Two Security Vulnerabilities in the Spring Framework’s MVC