Authlibは、空のHMACキーを受け入れ、これによりJWS/JWTの署名偽造(HS256/HS384/HS512)が可能になる。

報告者:Cavan Loughran、Celvex Group Inc.

概要

Authlibの対称(オクト)キーの処理において、有効なHMAC署名および検証キーとして、空のキー(空のバイト列 b'' または空の文字列 '')が受け入れられる。空のHMACキーを使用すると、どの当事者でも再現可能な決定論的なハッシュ値が生成されるため、アプリケーションが空のキーを使用してトークンを検証するように攻撃者が操作できた場合、攻撃者はHS256/HS384/HS512の署名検証を通過する任意のトークンを偽造できる。これは、すでにCVE-2026-44351(fast-jwt、npm)およびCVE-2026-45363(ruby-jwt、RubyGems)に脆弱性が報告されている、クロス言語の空のHMACキーに関連する問題である。

これは、Authlibの既存の最近のJWT検証に関する注意点とは異なる。CVE-2026-27962 / GHSA-wvwj-cvrp-7pv5(JWS JWKヘッダーインジェクション、key=Noneの場合)、CVE-2026-28802 / GHSA-7wc2-qxgw-g8gg(alg:noneによる空白署名回避)、またはGHSA-5357-c2jx-v7qh(非対称公開鍵とのアルゴリズムの混同)によって修正されるものではない。これらの問題は、それぞれヘッダー駆動のキーインジェクション、noneアルゴリズム、および非対称と対称の混同に対処するものであり、いずれもゼロ長のオクトキーを拒否しない。

影響を受けるバージョン

Authlib <= 1.7.2(最新リリース版は1.7.2、2026年5月6日)。v1.7.2のリリースタグおよび現在のmain HEADで確認されている。影響を受けるコードは、authlib/jose/rfc7518/oct_key.pyおよびauthlib/jose/rfc7518/jws_algs.pyにある。

根本原因(正確なコードの場所、リリースタグ v1.7.2)

- authlib/jose/rfc7518/oct_key.py, OctKeyクラス:
- validate_raw_keyは型チェックのみで、`return isinstance(key, bytes)`を返します。空のバイトオブジェクトは有効とみなされます。
- import_keyは、キーの内容が既知の危険なプレフィックスで始まる場合にのみ拒否します (`if raw_key.startswith(POSSIBLE_UNSAFE_KEYS): raise ValueError(...)`、つまりPEM/SSHのプレフィックス)。空のバイトはどの危険なプレフィックスにも一致しないため、b''は受け入れられます。
- get_op_keyは、生のキーの長さを検証せずにロードします。
- どこにもゼロ長のキーを拒否するチェックがないため、空のキーb''はすべてのチェックを通過します。
- authlib/jose/rfc7518/jws_algs.py, HMACAlgorithmクラス:
- prepare_key: `return OctKey.import_key(raw_data)`を返します。
- sign/verifyは、key.get_op_key(...)を呼び出し、その後`hmac.new(op_key, msg, self.hash_alg)`または`hmac.compare_digest(...)`を呼び出します。空のopキーの場合、これは`hmac.new(b'', ...)`となり、決定論的で、誰でも再現可能なハッシュ値になります。空のキーまたは最小長のチェックはありません。

なぜこれが実際の署名回避になるのか

空のHMACキーは、署名をヘッダーとペイロードの公開された決定論的な関数にするため、誰でも有効な署名を計算し、トークンを偽造できます。現実的なトリガーは、関連するCVEと一致します。デプロイされているアプリケーションは、実行時に空になる可能性のある場所から検証キーを読み込んでいます。例えば、os.environ.get('JWT_SECRET', '')、デフォルト値が空のデータベース/設定の列、またはキーが見つからない場合に''を返すキー解決機能などです。Authlibは、トークン検証器(OAuth 2.0のリソースサーバー、OIDCのリレーイングパーティー)を構築するために広く使用されており、Authlib自身の最近のセキュリティアドバイザリの履歴からもわかるように、JWS/JWTの検証パスが攻撃対象となる可能性が高いため、''を返す可能性のあるキー解決パスは、現実的な脆弱性につながる可能性があります。

再現方法(詳細な説明、悪用コードは含まない)

1. Authlibを使用してJWS/JWTを検証するアプリケーションにおいて、検証キーを空の値に設定します(例:未設定の環境変数をデフォルト値の空文字列に設定する)。
2. 攻撃者は、ヘッダーに{alg: HS256}、ペイロードに任意の値を設定したトークンを作成し、空のキーを使用してHS256の署名を計算します(キーが空であるため、どのユーザーでも同じ値を再現できます)。
3. AuthlibのHMAC検証機能は、このトークンを有効な署名付きとして受け入れます。なぜなら、OctKey.import_keyが空のキーを拒否せず、hmac.compare_digestが攻撃者が計算したハッシュ値と一致するためです。この偽造されたトークンは、正当なものとして扱われます。

実際に稼働しているシステムに対するテストは行われていません。上記は、この問題の性質を説明したものです。脆弱なコードパスと、存在しない保護機能は、v1.7.2の公開ソースコードおよび現在のmainブランチから直接確認されています。

修正が安全であることを確認(新規リスクがないことの証明)

同じ開発者が提供する、より新しいJOSEライブラリであるjoserfcは、すでに空のオクティングキーを完全に拒否しています。src/joserfc/_rfc7518/oct_key.pyのimport_key関数は、空のオクティングキーに対してValueErrorを発生させます。このエラーメッセージには、空のオクティングキーが決定論的なHMACハッシュ値を生成し、どのユーザーでも再現できるため、JWS HS256/HS384/HS512の検証において、簡単に署名を偽造できるという注意書きが含まれています。(joserfcは、さらに112ビット未満のキーに対して警告を発します。)同じ保護機能は、より古い、そして広く利用されているAuthlibのrfc7518パッケージには存在しません。主要なPython JOSEライブラリも同様の保護機能を備えています。PyJWTは、ゼロ長のキーに対してInvalidKeyError('HMAC key must not be empty.')を発生させ、jwcryptoはRFC 7518で規定された最小キー長を強制します。

影響

OAuth 2.0のリソースサーバーや、Authlibを基盤とするOIDCの依存関係において、実行時にHMAC検証キーが空になる場合、トークンの偽造や認証の回避が可能になります。攻撃者は、任意のクレーム(例えば、より高い権限を持つスコープや、別のユーザーの主体など)を持つトークンを作成し、署名検証を通過させることができます。

推奨される対策:

OctKey.import_key (および/または validate_raw_key) 関数において、空の OctKey マテリアルを拒否するように修正します。これは、保守者が提供している joserfc ライブラリが既に実装している方法と同じです。これにより、キーが HMACAlgorithm.sign / verify の hmac.new に到達する前に、不正なキーが使用されるのを防ぎます。また、HMAC キーに対して、joserfc ライブラリが採用している、112ビット未満の最小長に関する警告/拒否機能を導入することも検討してください。

情報開示

報告者: Cavan Loughran, Celvex Group Inc.

影響を受けるパッケージ:
- pip (Python) Authlib: 影響を受けるバージョンは 1.9.1 未満、1.9.1 で修正済み。