Shikata Ga Nai

Private? There is no such things.

JWT(JSON Web Token)診断マニュアル

Hello there, ('ω')ノ

🎯 1. JWTとは?

JWT(JSON Web Token) は、ユーザ情報や認証状態などをJSON形式で表現し、署名付きでクライアントに渡すトークン形式の認証手段です。 構造は3部構成:

[ヘッダー].[ペイロード].[署名]

例:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJ1c2VyIjoiYWRtaW4iLCJpYXQiOjE2Mjc5NDA2MDB9
.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

🧨 2. JWTに関する脆弱性とは?

JWT自体はセキュアな仕様ですが、実装や設定ミスにより重大な脆弱性を招くことがあります。

問題 内容 影響
alg = none 脆弱性 署名なしで受け入れてしまう 認証バイパス
鍵の予測可能性 弱い秘密鍵(例:"secret") 改ざん可
公開鍵を秘密鍵として扱う RSA公開鍵を使って署名が通ってしまう 認証偽造
トークンの有効期限無制限 セッション無限 セッション継続
パラメータ検証不足 権限昇格、IDなりすまし 情報漏洩・操作不正

🧭 3. 診断対象となる機能

機能 内容
ログイン後の認証トークン CookieやAuthorization: Bearer に含まれる
ログインせずに手動でトークンを送っても認証されるか
ロール(admin/user)などがトークン内にある場合 書き換えが可能か
トークンの署名が弱く改ざんできるか

🧪 4. テスト手順とペイロード

Step 1️⃣:トークンの構造を確認(デコード)

jwt.io や Burp の拡張機能を使用し、Base64でデコード:

Header:
{
  "alg": "HS256",
  "typ": "JWT"
}
Payload:
{
  "user": "admin",
  "exp": 1712345678
}

Step 2️⃣:alg の確認と変更(none攻撃)

Header:
{
  "alg": "none"
}
  • 署名部分を空にし、送信して認証が通るか確認
  • 通ったら → noneアルゴリズム脆弱性(重大)

Step 3️⃣:署名を再生成(鍵推測 or 鍵なし)

  • よくある弱い秘密鍵で署名を再生成して送信 例:secret, admin, password, 123456 など

ツール例:

# JWTを辞書で総当たり
python3 jwt_tool.py -t <token> -d <dict.txt>

Step 4️⃣:ペイロード改ざん(昇格など)

Payload:
{
  "user": "admin",
  "role": "admin"
}
  • 元は "role": "user" だったものを書き換えて送信 → サーバが署名を検証していなければ 認証バイパス可能

🔍 5. よくある脆弱な構成例

問題 解説
algnone 署名なしでトークンが通る(仕様上は廃止)
弱いHS256秘密鍵 HMAC鍵が推測・辞書攻撃で破られる
鍵交換処理ミス 公開鍵をHMACに使うことで署名偽造
exp チェックがない 無期限トークンが使い続けられる
トークンに権限・IDなど重要情報を含めている 改ざんにより特権奪取されやすい

🧰 6. 使用ツール

ツール 用途
jwt.io デコード / 再エンコードに便利
jwt_tool.py(GitHub) none攻撃、辞書攻撃、署名改ざんの自動化
Burp Suite + JWT Editor Burpでトークンを直接編集・再送
Hashcat / John the Ripper 鍵のクラックに使用可能(HMAC対応)

🔐 7. 安全なJWT実装のポイント

項目 説明
alg の強制(例:RS256) none や意図しないアルゴリズムの使用を防止
鍵管理の厳格化 長くてランダムなキーを使用し、公開/非公開を正しく扱う
署名検証の強制 検証をスキップしない、必ず行う
有効期限(exp)の設定とチェック セッション管理を適切に行う
JWTのリプレイ防止 ブラックリスト、トークンID(jti)の管理など

✅ 診断チェックリスト

チェック内容 OKなら ✔
alg=none にしても拒否されるか?
鍵が強固で辞書攻撃に耐えられるか?
トークンの改ざんで認証昇格できないか?
トークンに期限 (exp) が設定されているか?
ペイロード内の権限情報が改ざん耐性を持つか?

📌 見つけやすいヒント

  • Authorization: Bearer <token> ヘッダ
  • Cookie名が jwt, auth_token, access_token など
  • eyJ... で始まるBase64文字列
  • ペイロードに "role", "user", "admin" などが含まれる

Best regards, (^^ゞ