Mass Assignment / Over-Posting: Definindo isAdmin pelo Corpo da Requisição
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
- Reconhecer mass assignment quando um servidor vincula o JSON do cliente diretamente a um modelo privilegiado
- Identificar um campo sensível (isAdmin) presente no corpo da requisição que a interface nunca expõe
- Alterar um campo booleano em uma requisição capturada e reenviá-la para escalar privilégios
- Ler a resposta de uma API para confirmar que um painel de admin e dados privilegiados foram liberados
- Explicar por que atributos de autorização devem ser definidos pela lógica do servidor, e não vinculados a partir da entrada
Habilidades testadas
Pré-requisitos
- Entendimento básico de requisições HTTP, corpos JSON e envios de formulário
- Familiaridade com a ideia de um papel de admin versus um usuário normal
Como funciona
Mass assignment - também chamado de over-posting ou auto-binding - acontece quando um framework mapeia os campos de um corpo de requisição recebido diretamente para um objeto de domínio, e o desenvolvedor nunca restringe quais campos são permitidos. O recurso de conveniência que copia displayName do JSON para o registro do usuário vai copiar, com a mesma facilidade, isAdmin, role, balance, ou emailVerified se o atacante os adicionar, porque o binder não sabe quais campos são sensíveis.
O indício aqui é que o corpo da requisição carrega um campo que o formulário nunca mostrou. Um formulário de perfil normal permite editar um nome de exibição; ele não renderiza um interruptor de admin. Mas a requisição subjacente é apenas JSON, totalmente editável, e o servidor vincula o objeto inteiro. Definir isAdmin como true não é explorar um bug de parser - o valor é um booleano perfeitamente válido. A falha é que uma flag de privilégio chegou a ser alcançável através de vinculação controlada pelo usuário.
Isso é uma forma de escalada de privilégio e controle de acesso quebrado. O mesmo padrão permite que atacantes verifiquem o próprio email, concedam crédito a si mesmos ou alterem o id de outro usuário, dependendo de quais colunas o modelo expõe. A defesa robusta é vincular apenas uma lista de permissão explícita dos campos editáveis pelo usuário e definir todo atributo de autorização a partir de lógica de servidor confiável.
Erros comuns
- Assumir que a requisição só pode conter os campos que o formulário exibiu, quando o corpo é JSON puro que você pode editar ou adicionar livremente.
- Tentar payloads de injeção no nome de exibição em vez de notar a flag booleana de privilégio presente no corpo.
- Enviar um valor não booleano como
1ouyese desistir quando o servidor rejeitar - o campo é validado como booleano, então o valor precisa sertrue. - Tratar isso como um bug de interface em vez da falha real: o servidor nunca deveria vincular um campo de privilégio a partir da requisição.
Como se proteger
Vincule apenas uma lista de permissão explícita dos campos que um usuário pode alterar, e defina os atributos de autorização somente a partir da lógica do lado do servidor. O corpo da requisição nunca deveria conseguir escrever em uma coluna de privilégio - se isAdmin chegar no JSON, descarte-o em vez de honrá-lo.
- Use uma lista de permissão do lado do servidor (ou um DTO de entrada dedicado) listando exatamente os campos editáveis, como
displayName; ignore qualquer outra coisa no corpo. - Nunca exponha colunas sensíveis (
isAdmin,role,balance,emailVerified) ao auto-binder; defina-as apenas através de caminhos de código controlados e auditados. - Aplique uma verificação de autorização separada para mudanças de papel - conceder admin deve exigir um ator admin, não um salvamento de perfil autoatendido.
- Registre e alerte quando uma requisição tentar definir um campo privilegiado, para que tentativas de over-posting fiquem visíveis.