alltools.one
Security
2025-06-12
8 min
alltools.one Team
JWTSecurityAuthenticationAPIWeb Security

Segurança de JSON Web Tokens: Vulnerabilidades Comuns e Correções

Os JWTs são o padrão de facto para autenticação de APIs, mas a sua aparente simplicidade esconde verdadeiras armadilhas de segurança. JWTs mal configurados levaram a contornos de autenticação, escalação de privilégios e violações de dados. Este guia abrange as vulnerabilidades mais críticas e como preveni-las.

Recapitulação da Estrutura JWT

Um JWT consiste em três partes codificadas em Base64URL separadas por pontos:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.signature
  • Cabeçalho: Algoritmo e tipo de token
  • Payload: Claims (dados do utilizador, expiração, etc.)
  • Assinatura: Verificação criptográfica

Inspecione a estrutura JWT com o nosso Codificador/Descodificador JWT.

Para uma compreensão fundamental da estrutura JWT, consulte o nosso guia JWT Tokens Explicados.

Vulnerabilidades Críticas

1. Ataque de Confusão de Algoritmo

A vulnerabilidade JWT mais perigosa. Se um servidor aceitar o cabeçalho alg do token sem validação, um atacante pode:

Ataque: Alterar o algoritmo de RS256 (assimétrico) para HS256 (simétrico) e assinar o token forjado com a chave pública do servidor:

// Attacker's forged token
header: { "alg": "HS256", "typ": "JWT" }
payload: { "sub": "admin", "role": "superadmin" }
// Signed with the server's PUBLIC key as the HMAC secret

Se o servidor verificar tokens HS256 utilizando a chave pública como segredo, o token forjado passa na verificação.

Correção: Especifique sempre o algoritmo esperado explicitamente:

// WRONG - accepts whatever algorithm the token specifies
jwt.verify(token, key);

// CORRECT - enforce specific algorithm
jwt.verify(token, key, { algorithms: ['RS256'] });

2. Ataque de Algoritmo None

Algumas bibliotecas aceitam "alg": "none" — um token sem assinatura:

// Forged token with no signature
header: { "alg": "none", "typ": "JWT" }
payload: { "sub": "admin", "role": "superadmin" }
signature: ""  // empty

Correção: Nunca permita o algoritmo none em produção. Coloque explicitamente em lista branca os algoritmos permitidos.

3. Segredos de Assinatura Fracos

JWTs baseados em HMAC (HS256/HS384/HS512) são apenas tão fortes quanto o segredo:

// TERRIBLE - can be brute-forced in seconds
secret = "password123"

// WEAK - dictionary attack vulnerable
secret = "my-jwt-secret"

// STRONG - 256+ bits of randomness
secret = "a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0"

Correção: Utilize pelo menos 256 bits de aleatoriedade criptográfica para segredos HMAC. Melhor ainda, utilize chaves assimétricas (RS256, ES256) onde a chave de assinatura nunca precisa de ser partilhada.

4. Expiração em Falta

Tokens sem expiração nunca expiram — um token roubado concede acesso permanente:

// WRONG - no expiration
{ "sub": "user123", "role": "admin" }

// CORRECT - short expiration
{
  "sub": "user123",
  "role": "admin",
  "exp": 1705312800,
  "iat": 1705309200,
  "nbf": 1705309200
}

Boa prática: Tokens de acesso expiram em 15-60 minutos. Utilize refresh tokens (armazenados de forma segura) para sessões longas.

5. Dados Sensíveis no Payload

Os payloads JWT são codificados em Base64URL, não encriptados. Qualquer pessoa pode descodificá-los:

echo "eyJzdWIiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ" | base64 -d
# {"sub":"123","role":"admin"}

Nunca inclua: Palavras-passe, chaves de API, números de cartão de crédito, dados pessoais (NIF, registos médicos) ou qualquer segredo nos payloads JWT.

6. Armazenamento de Tokens (XSS vs CSRF)

ArmazenamentoVulnerável a XSSVulnerável a CSRF
localStorageSimNão
Cookie (sem flags)SimSim
Cookie HttpOnlyNãoSim
Cookie HttpOnly + SameSiteNãoNão

Recomendado: Armazene JWTs em cookies HttpOnly, Secure, SameSite=Strict. Isto previne o acesso por JavaScript (defesa contra XSS) e pedidos cross-site (defesa contra CSRF).

Set-Cookie: token=eyJ...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600

Lista de Verificação de Segurança

  1. Especificar algoritmos explicitamente — nunca aceitar do cabeçalho do token
  2. Rejeitar algoritmo none — exigir sempre uma assinatura
  3. Utilizar segredos fortes — 256+ bits para HMAC, 2048+ bits para RSA
  4. Definir expiração curta — 15-60 minutos para tokens de acesso
  5. Validar todos os claimsexp, iss, aud, nbf
  6. Armazenar em cookies HttpOnly — não em localStorage
  7. Rodar segredos periodicamente — planear a rotação de chaves
  8. Nunca armazenar dados sensíveis no payload
  9. Utilizar chaves assimétricas para sistemas distribuídos (RS256 ou ES256)
  10. Implementar revogação de tokens — lista negra ou expiração curta + refresh tokens

Assinatura Assimétrica vs Simétrica

AspetoHS256 (Simétrico)RS256 (Assimétrico)
ChaveSegredo partilhadoPar de chaves privada/pública
Quem pode assinarQualquer um com o segredoApenas o detentor da chave privada
Quem pode verificarQualquer um com o segredoQualquer um com a chave pública
Distribuição de chavesO segredo deve ser partilhado de forma seguraApenas a chave pública é partilhada
DesempenhoMais rápidoMais lento
Ideal paraServiço únicoMicrosserviços, sistemas distribuídos

Recomendação: Utilize ES256 (ECDSA) para novas aplicações — oferece segurança assimétrica com desempenho próximo do HMAC.

Estratégias de Revogação de Tokens

Os JWTs são stateless por design — não existe uma forma integrada de os revogar. Estratégias:

  1. Expiração curta: Se os tokens expiram em 15 minutos, a janela de um token roubado é limitada
  2. Rotação de refresh tokens: Emitir um novo refresh token a cada utilização; se um refresh token for utilizado duas vezes, revogar todos os tokens
  3. Lista negra: Armazenar IDs de tokens revogados (claims jti) e verificar em cada pedido
  4. Versionamento de tokens: Incluir um número de versão nos claims; incrementar a versão do utilizador ao terminar sessão

FAQ

Devo utilizar JWT ou cookies de sessão para autenticação?

Os cookies de sessão são mais simples e mais seguros para aplicações web tradicionais — o servidor controla o ciclo de vida da sessão e a revogação é instantânea. Os JWTs são melhores para APIs stateless, microsserviços e aplicações móveis onde o armazenamento de sessão no servidor é impraticável. Se escolher JWTs, implemente as medidas de segurança deste guia.

Qual é o tempo de expiração ideal para JWT?

Para tokens de acesso: 15-60 minutos. Mais curto é mais seguro mas requer atualização mais frequente. Para refresh tokens: 1-30 dias, armazenados em cookies HttpOnly. Para tokens de utilização única (verificação de email, reposição de palavra-passe): 1-24 horas.

Recursos Relacionados

Published on 2025-06-12
JSON Web Token Security: Common Vulnerabilities and Fixes | alltools.one