Shikata Ga Nai

Private? There is no such things.

alg: none” を使った攻撃(「署名なし(unsecured)」JWT受け入れ)

Hello there, ('ω')ノ

🧩 攻撃の流れ

  1. 正規ユーザーでJWTを取得 通常どおりログインし、JWTトークンを手に入れます。

  2. ヘッダの alg を改ざん JWTヘッダを Base64URL デコードして:

   {"alg":"HS256","typ":"JWT"}

を以下のように書き換え:

   {"alg":"none","typ":"JWT"}
  1. ペイロードを改ざん 例えば以下のように、sub(ユーザー名)や role(役割)を管理者に変更します。

  2. 署名部分を削除 alg=none にすると署名の検証が不要になります。トークンは、

   <base64ヘッダ>.<base64ペイロード>.

という末尾にドットだけの形式にします。

  1. 改ざんトークンを送信 脆弱なサーバーに送ると、署名検証せずにトークンを受け入れ、改ざんされたユーザーとして認識される可能性があります。

✅ 実際のラボ操作(PortSwigger の手順例)

  • Lab: JWT authentication bypass via flawed signature verification では、ヘッダ内の algnone に変更し、署名を削除して /admin へリクエスト送信するだけで攻撃が成功します。

⚠️ こんなケースで要注意!

  • alg=none 自体をきちんと禁止していない
  • サーバー側がヘッダの alg 値を 信頼している
  • ライブラリの decode() 関数だけ使って verify() を呼んでいない

🛡 対策

対策 説明
alg=none を拒否 明示的にホワイトリストで受け入れアルゴリズム(HS256, RS256 等)を指定
署名検証は常に必要 decode() の前に経由する verify() を使用。単なるデコードではなく、改ざん検知を徹底
ライブラリ設定を確認 none を無効化する設定が存在する場合は必ず ON に
トークン検証をログ監査 不正なtokenが来た場合に警告やログに記録して検知しやすく

🔚 まとめ

alg=none を正式にサポートする実装の甘さを突く、JWTにおける典型的かつ重大な脆弱性です。現代的な対応としては:

  • アルゴリズム許可リスト
  • 常に署名検証
  • decode() の濫用禁止

が鍵です。

Best regards, (^^ゞ