hunt-forgot-password について
パスワードリセットフローを調査するセキュリティテスト用スキルです。ユーザー名の列挙、リセットトークンの露出や再利用、レート制限の欠如を検査し、アカウント乗っ取りリスクとの関連も確認します。
主な機能
- 01有効・無効なユーザー名への応答比較
- 02リセットトークンの露出と予測可能性の確認
- 03トークン再利用と有効期限の検査
- 04リセットAPIのレート制限確認
- 05トークン紐付けとReferer漏えいの評価
活用シーン
- 01リセット応答による既存アカウント漏えいの確認
- 02トークンの再利用や長期有効性の検証
- 03リセット要求へのレート制限の検査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-forgot-passwordインストール後、Claude Code で/hunt-forgot-passwordを入力して読み込まれたか確認します。
詳細
自律テストの優先順位
まずユーザー名の列挙から始めましょう。最も手早く成果が得られ、後続のテストを進めるうえで重要です。
パターン 1 — ユーザー名の列挙(有効なメールアドレスと無効なメールアドレスで応答が異なる):
- 明らかに無効なメールアドレス(例:
[email protected])を使って、パスワード忘れのエンドポイントに POST します。応答本文、ステータスコード、長さを記録します - 存在することが分かっているメールアドレス(または
[email protected]、[email protected]、[email protected]のような一般的なパターン)を使って POST します - 応答を比較します。「メールを送信しました」と「メールアドレスが見つかりません」のようにメッセージが異なる、HTTP ステータスが異なる、または本文の長さに明確な差がある場合は、ユーザー名の列挙が確認されています
- 証明:基準値とプローブの 2 つの応答で、メッセージ本文、ステータスコード、または本文の長さに測定可能な違いがあれば、列挙が確認されています
パターン 2 — API 応答にリセットトークンが露出する: API によっては、リセットトークンをメールで送信するだけでなく、応答本文に直接返すことがあります。パスワード忘れのエンドポイントに POST し、JSON/HTML 応答にトークン、リンク、またはコードが含まれていないか確認します。パスワードをリセットできるトークンが現れた場合、即座にアカウントを乗っ取られる可能性があります。
パターン 3 — リセットトークンの再利用(使用後も再利用可能):
- パスワードのリセット手順を最初から最後まで実行します:トークンをリクエスト → そのトークンを使ってパスワードをリセット
- すぐに同じトークンをリセットパスワードのエンドポイントに再送信します
- 2 回目の送信が 200 または「成功」を返す場合 → 使用後にトークンが無効化されていません
パターン 4 — リセットリクエストのレート制限がない: 同じメールアドレスを使って、パスワード忘れのエンドポイントに短時間で 10~20 回送信します。429、ロックアウト、CAPTCHA がなく、すべて成功する場合 → レート制限がありません(列挙やトークンの大量送信が可能です)。
**コンテンツタイプ:**パスワード忘れのエンドポイントは、多くの場合 JSON ベースの REST API です。エンドポイントが従来型の HTML フォームである場合に限り、application/x-www-form-urlencoded を使用します(フォームのエンコーディングを確認するには、ログインページの HTML を確認してください)。
**証明:**ユーザー名の列挙=測定可能な応答の違い(本文/ステータス/長さ)。トークンの露出=応答本文にトークンが含まれること。トークンの再利用=使用済みトークンを 2 回目に使っても成功すること。
このスキルにおける脆弱性の種類
1. パスワードリセットによるユーザー名の列挙
有効なアカウントと無効なアカウントでエラーメッセージが異なると、認証なしでユーザー一覧が漏えいします。応答時間の差(「ユーザーが見つかりません」は速く、「メールをキューに追加しました」は遅い)も該当します。
価値の高い標的:管理者アカウント、従業員のメールアドレスのパターン、ユーザー名から推測できる API キー。
2. 脆弱な/予測可能なリセットトークン
タイムスタンプ、ユーザー名、または連番 ID から導出されたリセットトークンは、総当たりで推測できる可能性があります:
base64(email + timestamp)— デコード可能- 4~6 桁の数字コード — 1 万通りの推測が必要ですが、レート制限がなければ簡単に試行できます
- 連番の
token=1234、token=1235— 容易に列挙可能
3. トークンがセッションまたは IP に紐付いていない
多くのアプリはトークンを生成してメールで送信し、どのブラウザーからでも受け付けます。適切に紐付けられたトークンは、同じ IP からのみ使用できるか、元のセッションクッキーを要求すべきです。どちらも強制されていない場合 → リンクの転送によってアカウントが乗っ取られる可能性があります。
Referer/サードパーティーリソース経由のトークン漏えい。 トークンがリセットページの URL(/reset?token=…)に含まれ、そのページがクロスオリジンのリソース(アナリティクス、広告、フォント、CDN の画像など)を読み込むと、トークンを含む完全な URL が Referer ヘッダーでそのサードパーティーに漏えいします。リセットページからの送信リクエストを確認してください。クロスオリジンの Referer にトークンが含まれている場合、被害者の受信トレイにアクセスしなくても窃取できます。同じ漏えいは、<meta name=referrer> の設定ミスや、被害者がリセットページからクリックする外部リンクでも発生します。公表されたトークン漏えいからのアカウント乗っ取りクラスの事例:https://hackerone.com/reports/173551。
4. リセットリンクが有効期限切れにならない
一般的なベストプラクティス:リセットトークンは約 15~60 分以内に期限切れにします(RFC に厳密な値の規定はありませんが、OWASP は短時間かつ 1 回のみ使用できる有効期間を推奨しています)。24 時間前のトークンがまだ使用できる場合 → フィッシング攻撃に悪用されるリスクがあります。
5. リセットエンドポイントにレート制限がない
上限のないリセットエンドポイントでは、次のことが可能になります。
- メールの大量送信(被害者の受信トレイに対するDoS)
- トークンの候補が少ない場合のトークン総当たり
- 大規模なユーザー名の列挙
関連スキル
hunt-ato— アカウント乗っ取りのCHAINを担当します(パスワードリセットはそのパス#1です)。このスキルでは復旧フローのプリミティブを見つけて実証します。乗っ取り全体を組み立てるには、hunt-atoに引き継ぎます。hunt-cache-poison— リセットメールの生成中に発生するHostヘッダーインジェクション(異なる脆弱性ですが、同じフローです)hunt-brute-force— レート制限のテスト手法は、リセットエンドポイントにも適用できますhunt-auth-bypass— リセットフローを完全にスキップできる場合に使用します(空またはnullのトークンで/reset-password?token=にアクセス)hunt-mfa-bypass— リセット後にMFAが必須の場合は、そのバイパスをテストします