#desenvolvimento-de-software
#produto
#fundadores
Segurança

Troquei um número na URL e vi o pedido de outro cliente

Um cliente me chamou para uma segunda opinião no app que outra agência entregou. Em vinte minutos, só trocando um número no endereço, eu lia o pedido de outra empresa da plataforma. O login funcionava; a autorização, não. Sobre o buraco mais barato de evitar e o mais caro de achar tarde.

Por Victhor Araújo

Fundador da Revin. Engenheiro de formação, especialista em desenvolvimento de software e produtos digitais.

O cliente chegou por indicação, pedindo uma segunda opinião. A agência anterior tinha entregue o app dele fazia uns quatro meses, estava no ar, vendendo, e ele só queria saber se a casa estava em ordem antes de assinar a próxima fase com o mesmo pessoal.

Abri o painel numa conta de teste e olhei o endereço da página de um pedido. Terminava em algo como /pedidos/10432. Troquei o número para 10431 e apertei enter. Veio o pedido de outra empresa da plataforma: nome, valor, itens, e-mail de contato. Nenhum erro, nenhum aviso. Um 200 redondo, como se aquilo fosse meu.

Se você paga um fornecedor para construir o seu produto e nunca ninguém te mostrou como o acesso de um cliente fica separado do acesso do outro, este texto é para você.

Achado de segunda opinião quase nunca aparece na demo. Aparece quando alguém senta e testa o que o app faz com um pedido que não é seu.

Achado de segunda opinião quase nunca aparece na demo. Aparece quando alguém senta e testa o que o app faz com um pedido que não é seu.

Estar logado não é a mesma coisa que ter permissão

O erro tem nome e é o campeão das listas de segurança de aplicação faz anos: broken access control. Em português do dia a dia: o sistema conferiu quem você é na hora do login e parou por aí. Quando foi entregar aquele pedido específico, ele não perguntou de novo se o pedido era seu.

São duas perguntas diferentes, e é fácil confundir porque a primeira resolve a tela de login e cala a maioria dos testes manuais. A autenticação responde "você é o Victhor?". A autorização responde "esse pedido aqui é do Victhor?". A agência cuidou da primeira com esmero: token, expiração, tudo no lugar. Da segunda, não cuidou.

Num squad sênior essa segunda pergunta entra na definição de pronto do endpoint, não numa auditoria seis meses depois. É a diferença entre tratar autorização como camada da arquitetura e tratar como detalhe que dá para deixar pro fim. E o fim, spoiler, nunca chega.

Por que esse buraco aparece em quase todo app que a gente herda

A causa quase sempre é uma linha de código inocente. O dev pega o id que veio da URL e busca no banco: "me traz o pedido 10431". A consulta funciona, a tela renderiza, a demo passa. O que faltou foi um segundo filtro: "me traz o pedido 10431 que pertence a este usuário". Uma cláusula. É esse o tamanho do buraco.

Só que ela não aparece em lugar nenhum quando você olha o produto por cima. O cliente vê o pedido dele, tudo certo. Ninguém, num fluxo normal, digita o id de outra pessoa. O problema só existe para quem procura, e um fornecedor pago por feature entregue não tem incentivo para procurar. Isolar um cliente do outro não vira screenshot bonito no fim do sprint.

Separar o acesso de um cliente do outro é decisão de arquitetura, feita no papel antes do primeiro endpoint, não remendo aplicado depois que o dado já vazou.

Separar o acesso de um cliente do outro é decisão de arquitetura, feita no papel antes do primeiro endpoint, não remendo aplicado depois que o dado já vazou.

23 de 61 endpoints, e ninguém tinha reparado

Em 2024 a gente assumiu uma plataforma de logística com exatamente esse padrão. Rodava havia uns dois anos. Quando mapeamos os endpoints, 23 dos 61 que devolviam dado de cliente não checavam dono nenhum: bastava estar logado. Qualquer conta listava a entrega de qualquer outra trocando um id. Até onde deu para reconstruir dos logs, ninguém tinha explorado. Mas "ninguém explorou ainda" e "está seguro" são frases bem diferentes.

Esse 23 de 61 pode não ser representativo, e eu admito o viés: a gente é chamado justamente para os projetos que já cheiram a problema, então minha amostra pende para o caos. Ainda assim, mesmo nos apps que chegam relativamente saudáveis, é raro o inventário de autorização dar zero furo na primeira passada. O padrão se repete demais para ser azar.

Como a gente fecha isso por padrão 🔒

A regra que a Revin aplica em todo cliente é chata de tão simples: nenhum endpoint que recebe um id vai para produção sem um teste que tenta ler o dado de outro dono e exige um 403 de volta. Não é o teste do caminho feliz, é o do caminho malicioso. E ele mora no CI, roda a cada pull request, não depende de ninguém lembrar.

  • Filtro por dono na consulta: toda query de leitura carrega o usuário, nunca só o id do recurso.
  • Teste negativo no CI: para cada endpoint, um caso que tenta o acesso indevido e espera 403 ou 404.
  • Camada de política central: a decisão de "pode ver?" vive num lugar só, não espalhada em cada controller onde alguém esquece.

Se você não sabe dizer quantos dos seus endpoints checam dono hoje, esse é o tipo de coisa que a gente abre num diagnóstico de 30 minutos: https://revin.com.br/pt/diagnostic-sprint. Leva menos tempo que a reunião em que o problema vira crise.

O que eu falei para aquele cliente

Não falei para processar a agência anterior nem para refazer tudo do zero. Refazer do zero quase nunca é a resposta, e isso é papo de outro dia. Falei para ele parar de assinar a próxima fase com quem tratou separação de acesso como opcional, e para exigir, de quem continuasse, um teste de autorização por endpoint no pipeline. É verificável. Ou está lá rodando, ou não está.

A parte boa desse problema é que fechar custa pouco quando alguém decide olhar. Descobrir tarde, com um cliente perguntando por que viu o dado do vizinho, custa o resto. Se você quer uma leitura honesta de como o seu acesso está separado hoje, a conversa começa aqui: https://revin.com.br/pt/agende-uma-chamada.

Pronto para elevar o seu negócio?

Agendar uma reunião
Compartilhe
Link de compartilhamento LinkedinLink de compartilhamento XLink de compartilhamento WhatsappLink de compartilhamento Facebook
Você também pode gostar

A cada quinze dias. As decisões técnicas que tomamos, e o que aprendemos.