$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-forgot-passwordHunt Forgot Password / Account Recovery Authentication Flaws — 5 distinct patterns: (1) username enumeration via different responses for valid vs invalid email, (2) reset token exposed directly in the API response body, (3) reset token not invalidated after use (replay), (4) pass
| 1 | ## Autonomous Testing Priority |
| 2 | |
| 3 | **Start with username enumeration — it's the fastest win and gates the rest.** |
| 4 | |
| 5 | **Pattern 1 — Username enumeration (response difference for valid vs invalid email):** |
| 6 | 1. POST to the forgot-password endpoint with a clearly invalid email (e.g. `nonexistent@fakedomain12345.com`) — record the response body, status code, and length |
| 7 | 2. POST with an email you know exists (or try common patterns like `admin@target.com`, `test@target.com`, `user@target.com`) |
| 8 | 3. Compare responses: different message ("Email sent" vs "Email not found"), different HTTP status, or meaningfully different body length = username enumeration confirmed |
| 9 | 4. Proof: enumeration is confirmed when the two responses differ measurably (baseline vs probe) in message text, status code, or body length |
| 10 | |
| 11 | **Pattern 2 — Reset token exposed in the API response:** |
| 12 | Some APIs return the reset token directly in the response body (instead of only emailing it). POST to the forgot-password endpoint and look for a token, link, or code in the JSON/HTML response. If a token appears that lets you reset the password, that's an immediate account-takeover vector. |
| 13 | |
| 14 | **Pattern 3 — Reset token replay (reuse after use):** |
| 15 | 1. Complete a full password reset cycle: request token → use it to reset password |
| 16 | 2. Immediately try submitting the same token again to the reset-password endpoint |
| 17 | 3. If the second submission returns 200 or "success" → token not invalidated after use |
| 18 | |
| 19 | **Pattern 4 — No rate limit on reset requests:** |
| 20 | Submit the forgot-password endpoint 10-20 times rapidly with the same email. If all succeed without a 429, lockout, or CAPTCHA → no rate limit (enumeration + token flooding is possible). |
| 21 | |
| 22 | **Content-type:** Forgot-password endpoints are often JSON-based REST APIs. Use `application/x-www-form-urlencoded` only if the endpoint is a traditional HTML form (check the login page's HTML to determine form encoding). |
| 23 | |
| 24 | **Proof:** Username enumeration = measurably different response (body/status/length). Token exposure = token in response body. Token replay = second successful use of a consumed token. |
| 25 | |
| 26 | --- |
| 27 | |
| 28 | ## Vulnerability Classes in This Skill |
| 29 | |
| 30 | ### 1. Username Enumeration via Password Reset |
| 31 | Different error messages for valid vs invalid accounts leaks the user list without authentication. Even timing differences (fast "no user found" vs slow "email queued") count. |
| 32 | |
| 33 | High-value targets: admin accounts, employee email patterns, API keys derived from usernames. |
| 34 | |
| 35 | ### 2. Weak / Predictable Reset Tokens |
| 36 | A reset token derived from timestamp, username, or sequential IDs can be brute-forced: |
| 37 | - `base64(email + timestamp)` — decodable |
| 38 | - 4-6 digit numeric code — 10K guesses, easily feasible with no rate limit |
| 39 | - Sequential `token=1234`, `token=1235` — trivially enumerable |
| 40 | |
| 41 | ### 3. Token Not Bound to Session or IP |
| 42 | Most apps generate a token, email it, and accept it from any browser. A truly bound token should only work from the same IP or require the original session cookie. If neither is enforced → link forwarding = account takeover. |
| 43 | |
| 44 | ### 4. Reset Link Doesn't Expire |
| 45 | Common best practice: reset tokens expire within ~15–60 minutes (no hard RFC mandates the exact value; OWASP recommends a short, single-use lifetime). If a token from 24 hours ago still works → persistence risk for phishing attacks. |
| 46 | |
| 47 | ### 5. No Rate Limit on Reset Endpoint |
| 48 | An uncapped reset endpoint enables: |
| 49 | - Email flooding (DoS against victim's inbox) |
| 50 | - Token brute-force if the token space is small |
| 51 | - Username enumeration at scale |
| 52 | |
| 53 | --- |
| 54 | |
| 55 | ## Related Skills |
| 56 | |
| 57 | - **`hunt-ato`** — owns the account-takeover CHAIN (password-reset is its path #1). This skill finds/proves the recovery-flow primitive; hand off to hunt-ato to assemble the full takeover. |
| 58 | - **`hunt-cache-poison`** — host-header injection during reset email generation (different vulnerability, same flow) |
| 59 | - **`hunt-brute-force`** — rate-limit testing pattern applies to the reset endpoint too |
| 60 | - **`hunt-auth-bypass`** — if the reset flow can be skipped entirely (go to `/reset-password?token=` with empty/n |