JWT: estrutura e vulnerabilidade
1) O que é o JWT e onde ele é usado
O JWT é um contêiner de afirmações (claims) compacto no formato 'Base64Url (header). Base64Url(payload). Base64Url(signature)`.
Usado para:- JWS (tokens assinados - autenticidade/integridade),
- JWE (tokens criptografados - privacidade),
- OIDC/OAuth2 como acesso/ID de tokens e autenticação service-to-service.
Os benefícios são autonomia, capacidade de armazenamento, pequenas despesas gerais. Contras: risco de validação errada, malas de retirada complexas.
2) Estrutura JWT
2. 1 Título (header, JSON)
Mínimo: algoritmo e ID da chave.
json
{ "alg": "ES256", "kid": "jwt-2025-10", "typ": "JWT" }
'alg': algoritmo de assinatura/criptografia (RS256/ES256/PS256/HS256 etc.).
'kid': ponteiro da chave (para rotação JWKS).
As fontes de chave opcionais são 'jku', 'x5u' (consulte vulnerabilidades do parágrafo 6. 3).
2. 2 Carga útil (payload, JSON)
Marcas padrão:- `iss` (issuer), `aud` (audience), `sub` (subject)
- 'exp', 'nbf', 'iat' (emitido)
- 'jti' (ID de tocador adequado para críticas)
- marca domain: «scope/roles», «tenant», «kyc _ level», etc.
2. 3 Assinatura (assinatura)
JWS = `sign(base64url(header) + "." + base64url(payload), private_key)`
Verificação: chave pública estritamente apropriada e exatamente o algoritmo que o servidor espera.
3) Invariantes básicos de verificação
1. O algoritmo é capturado pela configuração do servidor de recursos (allow-list), em vez de confiar no conteúdo 'header. alg`.
2. Verificar «iss» e «aud» para a coincidência exata, «exp/nbf» - tendo em conta o pequeno «clock _ skew» (£30-60s).
3. Recusar o tocador sem 'kid' apenas se a chave for única e não houver rotação; senão exigir 'kid'.
4. Não confiar em nenhuma marca sem autorização no nível de objeto (BOLA-first).
5. Parsing - depois da criptoprovia; verificação básica de tamanho antes da decodificação.
4) JWS vs JWE
JWS: assinado, mas lemos. Não coloque em payload PII/segredos.
JWE: criptografa payload; a integração é mais difícil, o modelo-chave é crítico.
Na maioria das APIs é suficiente JWS + proibição de dados sensíveis no payload.
5) Ciclo de vida do token
Access: prazo curto (5 a 30 minutos).
Refresh: mais longo (7-30 dias), rotate-on-use (descartável), armazenar «lista negra» 'jti/sid'.
Revocation: listas de 'jti' com TTL, introspecção para opaque-tokens, redução de 'exp' em incidentes.
Rotação de chaves: JWKS com sobreposição (antigo + novo), consulte Rotação de chaves.
6) Vulnerabilidades frequentes e como fechá-las
6. 1 'alg = none '/troca de algoritmo
Essencial: o servidor confia no campo 'alg' e aceita o token não assinado.
Proteção: rígido allow-list algoritmos no servidor; rejeitar 'none' e valores inesperados.
6. 2 RS256→HS256 swap (simetrização)
Essencial: O agressor substitui 'alg' por HS256 e usa a chave pública como segredo HMAC.
Proteção: vincular a chave à configuração do algoritmo; não misturar provedores simétricos/assimétricos em um único 'kid'.
6. 3 Injeção de chaves ('kid/jku/x5u')
Cenários:- 'jku' indica um JWKS controlado por um intruso (subtrair sua chave).
- 'x5u '/' x5c' abuso de certificados externos.
- 'kid' com injeção de caminho/SQL ('".../.../privey. pem"' ou '"'OR 1 = 1 - "').
- Ignorar os 'jku/x5u' remotos ou filtrar por uma lista rigorosa de domínios.
- 'kid' usar apenas como chave no diretório local (tabela/kesh), sem caminhos de arquivo/concatenações SQL.
- JWKS carregar com URL confiável, TTL curto, assinatura/canal pinning.
6. 4 Segredos fracos HS256 (força bruta)
O segredo HMAC é curto/pato → trocar a assinatura.
Proteção: usar assimetria (RS/ES/PS) ou comprimento de segredo ≥ 256 bits, segredos apenas em KMS.
6. 5 Marcas ausentes/não-aleatórias
Não há 'aud '/' iss '/' exp' → o token de serviço cruzado é ou infinito.
Muito longo 'exp' → risco de comprometimento.
Proteção: exigir um conjunto completo de marcas, 'exp' curto, 'nbf '/' iat' validar com 'clock _ skew'.
6. 6 Replay e roubo de token
Essencial: interceptação/repetição de token (fuga em logs, XSS, MitM sem TLS).
Proteção:- TLS везде, `Secure`+`HttpOnly` cookie, SameSite=Lax/Strict.
- DPoP/PoP (vinculação do tocador à chave do cliente) e/ou mTLS para os parceiros.
- Curtas 'exp', rotação refresh, device-binding.
6. 7 Fugas via XSS/armazenamento
Essência: armazenamento JWT em 'localStorage '/' sessionStorage' → está disponível JS.
Proteção: Armazenamento de tocas access em HttpOnly-cookie (se possível cookie-model) + CSP/Trusted Types rigoroso.
Para SPA sem cookies - isolar o token na memória, viver minimamente, proteger contra XSS.
6. 8 CSRF
Essencial: quando as sessões de cookie são solicitadas por um site de terceiros.
Proteção: toquenis anti-CSRF (duplo submit), 'Origin/Referer', filtros Fetch-Metadata.
6. 9 Oversize/abuso de tamanho
A essência é um grande payload/cabeçalho DoS para parsing.
Proteção: limites de tamanho de cabeçalho/corpo, early-rejt 431/413, conjunto de marcas fix.
6. 10 Troca de 'typ '/' cty'
Essência: confusão de tipos ('typ:' JWT '), objetos JOSE aninhados.
Proteção: ignorar 'typ/cty' para segurança, e confiar em algoritmos fixos e marcações.
7) Armazenamento e transferência de tokens
7. 1 API de servidor (machine-to-machine)
mTLS/HMAC, de preferência assimetria para JWT, canais através de mesh.
Armazenamento de chaves - KMS/HSM, rotação programada, JWKS com sobreposição.
7. 2 Clientes de navegador
HttpOnly Secure Cookie для access/refresh; TTL curtos; atualização por «silent refresh» com «SameSite=None» apenas sob HTTPS.
CSP rigoroso, Trusted Types, proteja contra XSS; SPA - se possível, não armazenar o token no disco.
8) JWKS, roteiro e revisão
O JWKS é publicado por um utilizador automático; os consumidores escondem por 5-15 minutos.
Plano de rotação: adicionar um novo 'kid' começar a assiná-lo em N dias para remover o antigo do JWKS purge.
Levantamento: listas de 'jti/sid' c TTL; no incidente, reduzir temporariamente 'exp' e força-logout (deficiente refresh).
9) Multi-tenant e minimização de dados
Incluir 'tenant '/' org' apenas se for necessário pela arquitetura; caso contrário, puxar os atributos do PDP por 'sub'.
Nada de PII; um conjunto mínimo de marcas → menos risco de fuga e corelação.
10) Folha de cheque de validação prática (servidor do recurso)
- Parsim somente após verificar a assinatura e os limites básicos de tamanho.
- 'alg' da configuração; Rejeitar os inesperados.
- Verificar 'iss' n' aud ' ' exp ' ' nbf 'n' iat' (com 'clock _ skew').
- Verificar 'kid' pelo diretório local/JWKS (TTL curto).
- Filtrar/normalizar ponteiros externos ('jku/x5u' - apenas allow-list).
- Limitar comprimento/composição de marcas (padrão).
- Aplicar autorização de objeto para recurso (BOLA-first).
- Logar 'kid', 'sub', 'aud', 'iss', 'jti', 'exp', 'tenant', 'trace _ id' (sem PII).
- Métricas de erro de assinatura, atraso, auditoria de rotação.
11) Exemplos de políticas seguras (pseudo)
11. 1 Configuração de expectativas do algoritmo
yaml jwt:
expected_issuer: "https://auth. example. com"
expected_audience: ["wallet-service"]
allowed_algs: ["ES256"] # fix the jwks_url: "https ://auth. example. com/.well-known/jwks. json"
jwks_cache_ttl: 600s clock_skew: 60s required_claims: ["iss","aud","sub","exp","iat"]
11. 2 Rejeição remota 'jku/x5u'
yaml reject_untrusted_key_sources: true allowed_jku_hosts: ["auth. example. com"] # if absolutely necessary
11. 3 Exemplo de lista de comentários (Redis)
pseudo if redis. exists("revoke:jti:" + jti) then deny()
if now() > exp then deny()
12) Observabilidade e forensica
Метрики: `jwt_verify_fail_total{reason}`, `jwt_expired_total`, `jwks_refresh_total`, доля `kid`.
Logi (estruturado): 'iss/aud/sub/kid/jti/exp/tenant/trace _ id', causa da falha.
Dashboards: «em breve», aumento de erros de validação, distribuição por região/cliente.
Alerts: altura de 'verify _ fail' (assinatura/algoritmo), erros de JWKS, proporção de tokens vencidos.
13) Antipattern
Confiar em 'alg' do token; suportar 'none'.
Acesso de longa duração e falta de rotação refresh.
HS256 com segredo curto/segredo em ENV sem KMS.
Aceitar 'jku/x5u' de qualquer domínio; carregar dinamicamente o JWKS sem allow-list.
Coloque PII/segredos no payload JWS.
Armazenar tokens em 'localStorage' se houver riscos XSS.
Abafar erros de validação (devolver 200 com «soft error»).
Falta de verificação de BOLA e dependência apenas de 'scope/role'.
14) Especificidades do iGaming/Finanças
Marca: 'kyc _ level', 'risk _ tier', 'tenant', 'aud' rigoroso.
TTL curtos para transações write (depósitos/conclusões), PoP/DPoP ou mTLS para rotas críticas.
Auditoria regulatória: registros de entrada/rejeição imutáveis, armazenamento de logs nos limites da região.
Os parceiros/PSP têm chaves individuais/' aud ', chaves para tenante e JWKS individuais.
15) Folha de cheque pró-prontidão
- Rígido allow-list algoritmos; 'none' não é permitido.
- 'iss/aud/exp/nbf/iat/jti' são verificados; curtas 'exp'.
- JWKS com sobreposição, curto TTL de cachê; monitoramento da parte 'kid'.
- Refresh — rotate-on-use; listas de 'jti/sid' com TTL; playbook de comentários.
- PoP/DPoP ou mTLS em rotas críticas.
- HttpOnly-cookies para navegador, CSP/Trusted Types vs XSS; Proteção CSRF.
- Sem PII no payload; um conjunto mínimo de marcas.
- Métricas/logs de validação e falha; alert JWKS/verify _ fail.
- Testes de cenários negativos: RS→HS swap, 'kid' -inecção, 'jku' spoofing, oversize, clock-skew.
16) TL; DR
Fixe o algoritmo e as chaves no lado do servidor, não confie em 'alg' do token, exija 'iss/aud/exp/nbf/iat/jti'. Rotue as chaves através do JWKS com sobreposição, mantenha os tokens curtos e refresh descartáveis. Guarde os tokens com segurança (HttpOnly-cookie para web), minimize as marcas, não coloque o PII. Feche 'jku/x5u/kid' - controladores, evite HS256 com segredos fracos, adicione PoP/DPoP ou mTLS em caminhos críticos e faça sempre testes BOLA ao nível do recurso.