【テクニカル・上級編】JWTのalg: none攻撃と鍵混同攻撃(Key Confusion Attack) – アプリケーションセキュリティ & 安全な開発防御ガイド

JWTの脆い牙城:alg: noneと鍵混同攻撃が突きつける「実装の過信」という罠

セキュリティアーキテクトとして多くのコードベースを監査してきたが、JWT(JSON Web Token)ほど「便利さと危うさが紙一重」なプロトコルは他にない。開発者は往々にして、ライブラリの抽象化レイヤーの背後に隠れた「暗号学的妥当性」を過信しがちだ。

特に、JWTの構造を深く理解せず、単なる「セッション管理のトークン」としてのみ扱う設計は、脆弱性への招待状に他ならない。今回は、古くて新しい、しかし未だに現場で散見されるJWTの致命的な欠陥、alg: none攻撃と鍵混同攻撃(Key Confusion Attack)の本質を解剖する。

—

1. alg: none攻撃:プロトコル仕様の「おもてなし」が招く脆弱性

JWTのヘッダーにある alg パラメータは、検証者が署名をどう検証すべきかを指示するものだ。しかし、この仕様には最初から「none」という選択肢が含まれていた。これはデバッグ用や、通信路がTLSで完全に保護されていると仮定した場合のパフォーマンス最適化を意図したものだが、現実はこれほど甘くない。

攻撃のメカニズム

攻撃者は、JWTのペイロードを改ざん(例: {"user": "admin"})した後、ヘッダーを以下のように書き換える。

{
“alg”: “none”,
“typ”: “JWT”
}

サーバーサイドの検証ロジックが、「algがnoneなら署名検証をスキップする」という実装になっていれば、攻撃者は署名なしでなりすましが可能になる。

防御の鉄則:ホワイトリストによる厳格な強制

ライブラリのデフォルト設定を信じるな。検証ロジックでは、受け入れ可能なアルゴリズムをハードコードしたホワイトリストで制限することが唯一の解だ。

脆弱な実装例(NG)
jwt.decode(token, key, options={“verify_signature”: True})
^ これだとライブラリがalgを信用してしまう可能性がある

セキュアな実装例(OK)
期待するアルゴリズム(例: RS256)以外を一切許容しない
jwt.decode(
token,
public_key,
algorithms=[“RS256”] # ここで明示的に指定し、noneを排除する
)

—

2. 鍵混同攻撃(Key Confusion):非対称鍵を対称鍵として悪用する深淵

これはより巧妙だ。公開鍵暗号(RSA/ECDSA)を使用しているシステムに対し、攻撃者が公開鍵そのものを「HMACの秘密鍵」として認識させる攻撃である。

なぜこれが成立するのか?

多くのJWTライブラリは、秘密鍵を単なる「バイト列」として扱う。RSAの公開鍵はPEM形式で公開されているため、攻撃者はその公開鍵の文字列を取得し、それをHMACアルゴリズム(例: HS256)の「秘密鍵」として署名を生成する。

サーバー側が「ヘッダーでalg: HS256が指定されたから、公開鍵をHMAC用のキーとして使おう」と判断してしまった瞬間、検証は成功してしまう。本来、公開鍵を知っている誰でも署名が作れる状態、つまり認証の崩壊だ。

アーキテクチャでの防御:鍵のメタデータ分離

この脆弱性を防ぐためのアーキテクチャ設計として、「アルゴリズムと鍵の用途を分離した検証エンジン」を構築する必要がある。

1. 鍵の型チェック: 鍵のオブジェクトがRSAなのかHMAC用なのかを型レベルで厳密にチェックする。
2. 検証コンテキストの強制: algヘッダーに依存せず、エンドポイントごとに使用すべきアルゴリズムを検証側に固定する。

// 検証時にアルゴリズムを強制的に固定する(Node.js/jsonwebtokenの例)
jwt.verify(token, publicKey, {
algorithms: [‘RS256’], // HS256を指定されても検証を拒否する
issuer: ‘my-auth-server’
}, (err, decoded) => {
if (err) { / 署名不一致、あるいはalg不一致をハンドリング / }
});

—

3. 生成AI時代の新たな脅威:プロンプトインジェクションとトークン汚染

今、我々が直面しているのは、LLMが介在するパイプラインでのJWT悪用だ。生成AIがトークンの値を解釈し、その後のAPI呼び出しを行う場合、プロンプトインジェクションによってJWTのペイロードが「操作」される可能性がある。

推奨するガードレイル

  • ゼロトラスト・トークン検証: AIが生成したリクエストであっても、JWTの署名検証は必ずバックエンドのセキュリティゲートウェイで再実施する。
  • ペイロードの最小化: トークン内に「AIが解釈可能なメタデータ」を詰め込みすぎないこと。必要最小限のクレーム(sub, exp, iat)のみに絞り、権限情報はバックエンドの信頼できるDBから直接引く。

—

結び:セキュリティは「仕様」ではなく「実装の解釈」に宿る

JWTの問題は、プロトコルの仕様そのものというよりは、「仕様を柔軟に解釈しすぎたライブラリの実装」と、「それを疑わずに使ったエンジニアの設計」の間に生まれる。

CISSPの観点から言えば、これは「境界防御」ではなく「データ中心のセキュリティ」の失敗だ。ライブラリのバージョンを最新に保つことは最低条件だが、それ以上に「アルゴリズムの厳格な固定」という、極めて泥臭いコードレベルの防衛こそが、攻撃者の侵入を阻む最後の砦となる。

常に問え。「このライブラリは、私が意図しないアルゴリズムを許容する余地を残していないか?」と。その疑念こそが、最高峰のホワイトハッカーの第一歩である。

コメント

タイトルとURLをコピーしました