JWTの「署名検証」という幻想:アルゴリズム強制攻撃の深淵と防御の極意
多くのアーキテクトが「JWTは安全だ」という神話を盲信している。しかし、現実のフィールドにおいてJWTは、不適切な実装という名の「鍵のいらない玄関」を放置しているケースが後を絶たない。
特に alg ヘッダーを操作するアルゴリズム変更攻撃は、JWTの仕様そのものに潜む構造的欠陥を突く、極めて古典的かつ破壊的な手法だ。今回は、この攻撃のメカニズムを低レイヤから紐解き、我々がどのようにして堅牢な防衛ラインを構築すべきか、その「現場の知見」を共有する。
—
1. 脆弱性の核心:なぜ alg: none は悪魔の囁きなのか
JWTの仕様(RFC 7519)において、alg パラメータは「どのアルゴリズムで署名を検証すべきか」を定義する。脆弱なライブラリや実装は、このヘッダーの内容を無批判に受け入れ、検証処理のロジックを動的に切り替えてしまう。
攻撃シナリオ:強制的なアルゴリズムダウングレード
攻撃者は、JWTのヘッダーを以下のように書き換える。
{
"alg": "none",
"typ": "JWT"
}
サーバーサイドのコードが脆弱な場合、ライブラリは「alg が none なので、署名の検証は不要」と誤認する。この瞬間、ペイロードの改ざんは容易になる。"sub": "admin" と書き換えたJWTを送りつけるだけで、認証はバイパスされる。
公開鍵の秘密鍵化(HS256への強制)
より高度な攻撃では、RS256(非対称鍵)を使用しているシステムに対し、あえてHS256(対称鍵)を強制する。サーバー側が「公開鍵」を「HMACの共有鍵」として利用するように仕向けるのだ。公開鍵は公開されているため、攻撃者はこれを使って正規のHMAC署名を生成できてしまう。
—
2. 脆弱な実装とセキュアな実装の分かれ道
多くのエンジニアが犯すミスは、ライブラリの decode メソッドをそのまま呼び出し、期待するアルゴリズムを明示していないことにある。
脆弱な実装例(Node.js / jsonwebtoken)
// 絶対にやってはいけない実装
// 攻撃者がヘッダーの alg を操作した場合、検証がスルーされる可能性がある
const decoded = jwt.verify(token, publicKey);
セキュアな実装(アーキテクトの矜持)
検証時には、必ず期待するアルゴリズムをハードコードする。また、ライブラリが none を許可していないことを確認せよ。
// 推奨されるセキュアな検証
const decoded = jwt.verify(token, publicKey, {
algorithms: ['RS256'], // ここで許可するアルゴリズムを限定する
ignoreExpiration: false // 期限切れトークンを排除
});
// ライブラリの内部設定で、noneアルゴリズムのグローバルな無効化を推奨する
// 例: jsonwebtokenの場合、デフォルトで none は無効だが、明示的に検証ロジックをラップする
—
3. 防御のアーキテクチャ:多層防御のレイヤー
単にコードを修正するだけでは不十分だ。高セキュリティな環境では、以下のガードレールを設計に組み込む必要がある。
A. 鍵管理の厳格化
公開鍵を検証用として使用する場合、その鍵が「HMACの秘密鍵」として誤用されないよう、アプリケーションのメモリレイヤーで型定義やバリデーションを行う必要がある。可能な限り、鍵の用途を制限した JWK (JSON Web Key) を使用し、use パラメータで sig (Signature) を指定せよ。
B. インフラ層でのプロトコル・フィルタリング
生成AIや自動化されたボットによるプロンプトインジェクションと同様に、JWTの解析においても「不正なパケット構造」を弾くWAFの設定が重要だ。ヘッダー内に予期せぬ alg が含まれている場合、または alg が期待値と一致しない場合、即座にリクエストをドロップし、監視アラートを発報せよ。
C. 耐量子暗号(PQC)への移行を見据えて
現在広く使われているRSAやECDSAは、量子コンピュータの登場によって脅威にさらされる。JWTの署名アルゴリズムも、近い将来、耐量子性を備えたアルゴリズム(例: DilithiumやFalcon)への移行が議論されるべきフェーズにある。認証トークンの寿命を短く設定し、将来的なアルゴリズム変更に耐えうる「アジリティ(俊敏性)」をシステムアーキテクチャに持たせておくことが、真のプロフェッショナルの仕事だ。
—
結論:セキュリティは「性悪説」から始まる
JWTの脆弱性は、仕様の欠陥というよりは、「実装者が仕様を正しく理解し、制約をかけること」を放棄した結果に他ならない。
- 許可するアルゴリズムはホワイトリスト管理せよ。
- ヘッダーの入力を決して信頼するな。
- 鍵の用途を物理的・論理的に分離せよ。
我々の仕事は、コードを書くことではない。「攻撃者が入り込む余地を、計算可能な限りゼロに近づけること」である。この哲学を忘れず、今日もセキュアな設計を追求してほしい。
コメント