Mass Assignment / Over-Posting: Setting isAdmin from the Request Body
O desafio
Esta é a requisição que o app envia quando você salva o seu perfil. Ela envia os campos que o formulário mostra - mas o corpo também carrega uma flag isAdmin que o formulário nunca exibe, e o servidor salva o que recebe. Inverta essa flag, envie e leia o flag de admin que a resposta libera.
O que você vai aprender
- Recognize mass assignment when a server binds client JSON directly onto a privileged model
- Spot a sensitive field (isAdmin) carried in a request body that the UI never exposes
- Tamper a boolean field in a captured request and replay it to escalate privileges
- Read an API response to confirm an admin panel and privileged data were unlocked
- Explain why authorization attributes must be set by server logic, not bound from input
Habilidades testadas
Pré-requisitos
- Basic understanding of HTTP requests, JSON bodies, and form submissions
- Familiarity with the idea of an admin role versus a normal user
Como funciona
Mass assignment - also called over-posting or auto-binding - happens when a framework maps the fields of an incoming request body straight onto a domain object, and the developer never restricts which fields are allowed. The convenience feature that copies displayName from JSON onto the user record will just as happily copy isAdmin, role, balance, or emailVerified if the attacker adds them, because the binder does not know which fields are sensitive.
The tell here is that the request body carries a field the form never showed you. A normal profile form lets you edit a display name; it does not render an admin switch. But the underlying request is just JSON, fully editable, and the server binds the whole object. Setting isAdmin to true is not exploiting a parser bug - the value is a perfectly valid boolean. The flaw is that a privilege flag was ever reachable through user-controlled binding.
This is a form of privilege escalation and broken access control. The same pattern lets attackers verify their own email, grant themselves credit, or change another user's id, depending on which columns the model exposes. The robust defense is to bind only an explicit allow-list of user-editable fields and to set every authorization attribute from trusted server logic.
Erros comuns
- Assuming the request can only contain the fields the form displayed, when the body is plain JSON you can add to or edit freely.
- Trying injection payloads on the display name instead of noticing the boolean privilege flag sitting in the body.
- Sending a non-boolean like
1oryesand giving up when the server rejects it - the field is validated as a boolean, so the value must betrue. - Treating this as a UI bug rather than the real flaw: the server should never bind a privilege field from the request at all.
Como se proteger
Bind only an explicit allow-list of fields a user is permitted to change, and set authorization attributes from server-side logic alone. The request body should never be able to write to a privilege column - if isAdmin arrives in the JSON, drop it rather than honoring it.
- Use a server-side allow-list (or a dedicated input DTO) listing exactly the editable fields, such as
displayName; ignore anything else in the body. - Never expose sensitive columns (
isAdmin,role,balance,emailVerified) to the auto-binder; set them only through controlled, audited code paths. - Enforce a separate authorization check for role changes - granting admin must require an admin actor, not a self-service profile save.
- Log and alert when a request attempts to set a privileged field, so over-posting attempts are visible.