29 de MAIO
Bom dia, boa tarde ou boa noite.
Me chamo Cassio Shiga Casagrande e atuo como Analista de Cibersegurança Red Team na Integrasul.
Este é meu primeiro post no blog e a proposta aqui é ir direto ao ponto: conteúdo técnico, prático e baseado em cenários reais de exploração. A ideia não é apenas explicar conceitos, mas demonstrar como falhas surgem na prática, como podem ser exploradas e, principalmente, onde está o erro de implementação.
Neste artigo, vamos analisar um caso clássico envolvendo JSON Web Tokens (JWT), onde uma validação incorreta permite manipulação do token e escalada de privilégios, um exemplo claro de como pequenas decisões de implementação podem comprometer toda a segurança de uma aplicação.
O que é?
JSON Web Tokens (JWT) são amplamente utilizados como mecanismo de autenticação em aplicações modernas, principalmente em APIs REST e arquiteturas stateless.
Em cenários vulneráveis, um simples ajuste no token pode permitir que qualquer usuário se torne administrador sem conhecer segredo nenhum e sem quebrar a codificação.
Um JWT é composto por três partes:
• Header: define o algoritmo de assinatura
• Payload: contém as claims (dados do usuário)
• Signature: garante a integridade do token
Formato:
header.payload.signature
O ponto crítico aqui é simples: a assinatura é o único mecanismo de confiança.
Sem validação correta dela, todo o restante perde valor.
Onde mora o problema?
Apesar do payload ser apenas codificado (Base64URL) e não criptografado, muitas implementações tratam seu conteúdo como confiável.
Na prática, o token é totalmente manipulável pelo cliente.
Se a validação da assinatura for falha, um atacante pode:
• modificar os dados livremente
• forjar identidade
• escalar privilégios
• obter acesso total
E isso nos leva a um dos erros mais clássicos:
- Aceitar o algoritmo: none
Vulnerabilidade: alg: none
A especificação original do JWT prevê suporte ao algoritmo none, que indica ausência de assinatura.
{
"alg": "none",
"typ": "JWT"
}
Em implementações seguras, isso deve ser explicitamente bloqueado.
O problema aparece quando a aplicação:
• confia no alg vindo do cliente
• não força um algoritmo no backend
• ou utiliza bibliotecas/configurações inseguras
Nesses cenários, o servidor pode:
- aceitar tokens sem assinatura
- confiar integralmente no payload
Exploração passo a passo
Para demonstrar o cenário na prática, subi um laboratório simples com uma API local responsável por gerar e validar tokens JWT.
1. Obter um JWT válido
Ao acessar o endpoint de login (http://localhost:3000/login), a aplicação retorna um token válido:

O “curl” é uma ferramenta de linha de comando usada para enviar requisições HTTP de forma simples, permitindo testar endpoints, manipular headers (como Authorization) e reproduzir chamadas de API sem precisar de interface gráfica.
Ao enviar esse token junto ao curl para o endpoint /admin, temos a resposta de “Acesso Negado”.

2. Decodificar
O JWT utiliza Base64URL, o que torna seu conteúdo trivial de decodificar.
Isso pode ser feito via terminal (com conversão para Base64 padrão) ou de forma mais prática utilizando JWT.io

Com a função Decoder da ferramenta jwt.io conseguimos ver os dados do token.
3. Modificar a “role” do payload de “user” para “admin”
{
"user": "integrasul",
"role": "admin"
}
4. Alterar o “alg” no header de “HS256” para “none”
{
"alg": "none",
"typ": "JWT"
}
5. Regerar o token
base64(header) + "." + base64(payload) + "."
- Sem assinatura
Alterando para a função Encoder da ferramenta jwt.io conseguimos alterar os dados do token.
6. Enviar para a aplicação

Resultado
Se a aplicação for vulnerável, o comportamento é direto:
• o token é aceito
• o payload é confiado
• o atacante obtém privilégios administrativos
- sem segredo
- sem brute force
- sem quebrar criptografia
Impacto
Essa falha leva diretamente a:
• Account Takeover
• Privilege Escalation
• acesso à funções administrativas
• leitura/modificação de dados sensíveis
Em APIs, isso geralmente implica comprometimento total da aplicação.
Causa raiz
O problema não está no JWT em si, mas na forma como ele é validado. O backend confia em dados controlados pelo cliente para definir como aplicar segurança. O algoritmo (alg) vem do próprio token. Se não houver validação rígida no servidor, o atacante passa a controlar o processo.
Boas práticas
• Não confiar no alg do token
→ definir explicitamente os algoritmos aceitos no backend
• Validar sempre a assinatura
• Validar claims críticas (iss, aud, exp)
• Utilizar tokens de curta duração
• Armazenamento seguro no cliente
→ evitar localStorage
→ preferir cookies com HttpOnly, Secure, SameSite
Conclusão
JWT não é inseguro por definição. O risco surge quando a validação é mal implementada. Neste cenário, não foi necessário explorar nada complexo. Apenas manipular dados controlados pelo cliente. Quando a validação falha, o controle deixa de ser do servidor e passa a ser do atacante.