# Mass Assignment
Many web-frameworks automate the process of assigning parameters from an incoming HTTP request to the fields on an in-memory object. You need to ensure that you are using assignment logic in your code in such a way that only permitted fields are written to. Otherwise, an attacker can perform a **mass assignment** attack, overwriting sensitive data fields (like permissions and roles) they should not be able to access.
## Mass Assignment in Python
A common design pattern is to take data from an HTTP request – either the HTTP parameters or from JSON or XML in the body of the request – and to update the contents of an object in-memory or in the database. In Python, this design pattern in often achieved by using the `setattr(…)` function:
“`python class User(models.Model): ROLES = ( (‘G’, ‘Guest’), (‘U’, ‘User’), (‘A’, ‘Admin’), (‘S’, ‘Superuser’) )id = models.IntegerField() username = models.CharField(max_length=100) email = models.CharField(max_length=100) password = models.CharField(max_length=100) role = models.CharField(max_length=1, choices=ROLES) updated = models.DateTimeField() def profile(request): if user is None: if request.method == ‘POST’: # Danger: updating arbitrary fields on the user object from incoming JSON is dangerous! user.updated = datetime.now() return HttpResponse(“Profile updated”, 202) elif request.method == ‘GET’: return HttpResponseNotAllowed((‘GET’, ‘POST’)) |
This code is vulnerable to a *mass assignment* attack since the function allows the user to change anything in their profile – and specifically, it allows a user to change their role. Even if the `role` is not sent by client-side JavaScript code, an attacker can send their own JSON request that contains the extra field, and hence make themselves an administrator.
When mapping uploaded data to objects, *only* enumerate properties that you intend to be editable:
“`python if request.method == ‘POST’: data = json.loads(request.body)# Explicitly enumerating the fields to be updated protects us from mass-assignment. user.email = data.get(’email’, user.email) user.username = data.get(‘username’, user.username) user.updated = datetime.now() return HttpResponse(“Profile updated”, 202) |
## CWEs
* [CWE-915](https://cwe.mitre.org/data/definitions/915.html)