$npx -y skills add elementalsouls/Claude-BugHunter --skill hunt-brute-forceHunt Missing/Weak Rate Limiting — login brute force, OTP/2FA brute force (10^6 keyspace), password-reset-token brute, credential stuffing, username/email enumeration via error-string / status-code / timing differences, weak password policy, missing CAPTCHA (CAPTCHA token replay /
| 1 | # HUNT-BRUTE-FORCE — Rate Limiting / Brute Force / Enumeration |
| 2 | |
| 3 | > Grounding note: this skill is built from published technique classes, not from a |
| 4 | > curated set of named HackerOne reports. `report_count` is intentionally `0` — do |
| 5 | > not cite an exact payout or report ID you cannot verify. Where a public case is |
| 6 | > well-documented (e.g. Laxman Muthiyah's Instagram password-reset OTP race/rotation |
| 7 | > research, 2019–2021), it is named below as a *technique reference*, not a payout claim. |
| 8 | |
| 9 | ## Crown Jewel Targets |
| 10 | |
| 11 | OTP brute force (6-digit = 1,000,000 combinations) with no effective rate limit = Critical ATO bypass. |
| 12 | |
| 13 | **Highest-value chains:** |
| 14 | - **OTP / 2FA brute → MFA bypass → ATO** — no effective rate limit on `/verify-otp`, full 000000–999999 keyspace reachable |
| 15 | - **Password-reset token brute** — short/predictable/non-expiring tokens + no rate limit → ATO (the Instagram 2019 case combined a 6-digit reset code, no rate limit per request-source, and IP rotation to make 10^6 tractable) |
| 16 | - **Username/email enumeration → targeted credential stuffing** — valid/invalid distinguishable by response string, status code, or timing, then sprayed with breach corpora |
| 17 | - **Coupon / gift-card / referral code brute** — no rate limit on code validation → financial impact |
| 18 | - **ReDoS** — attacker-controlled input hits a catastrophic-backtracking regex → CPU exhaustion → DoS |
| 19 | |
| 20 | --- |
| 21 | |
| 22 | ## Autonomous Testing Priority |
| 23 | |
| 24 | **Work within your turn budget — prioritize signal over volume.** |
| 25 | |
| 26 | You cannot brute-force millions of combinations in automated testing. Focus on two things: (1) credential spraying with the most likely candidates, and (2) detecting whether rate limiting exists at all. |
| 27 | |
| 28 | **Strategy:** |
| 29 | 1. Identify the login endpoint and the expected parameter names (username/email, password). |
| 30 | 2. Try weak/default credentials likely for the target context — default admin credentials for the app's stack, simple passwords for test environments, credentials visible elsewhere on the app (e.g. usernames exposed in profiles, default passwords in documentation). |
| 31 | 3. After 3-5 failed attempts, check for rate-limit signals (429 status, "too many attempts" message, CAPTCHA appearance, account lockout message). Absence of these = rate limiting is missing = vulnerability. |
| 32 | 4. Use form-encoding for traditional login forms, JSON for REST API login endpoints. |
| 33 | |
| 34 | **What to look for as success:** |
| 35 | - Session token or JWT in the response body or Set-Cookie header |
| 36 | - Redirect to authenticated dashboard |
| 37 | - Response body that differs from the failed-login baseline |
| 38 | |
| 39 | **Username enumeration (separate finding):** Try a known-valid username vs a random one. If the error message differs ("Wrong password" vs "User not found") or response time differs → user enumeration vulnerability, even without a successful login. |
| 40 | |
| 41 | --- |
| 42 | |
| 43 | ## CRITICAL: Four rate-limit states — do not collapse them |
| 44 | |
| 45 | A `200`/`401` with no `429` does **not** mean "no rate limiting". A rate-limiting |
| 46 | skill that only checks for `429`/lockout produces false negatives. Classify the |
| 47 | defense BEFORE concluding, by sending a burst of ~50 requests and watching the |
| 48 | *full* response (status, body, headers, latency, and downstream success): |
| 49 | |
| 50 | | State | Signal | Brute still feasible? | |
| 51 | |-------|--------|-----------------------| |
| 52 | | **Hard account lockout** | account disabled after N fails; later *correct* creds also fail | No (but lockout itself can be a DoS finding) | |
| 53 | | **Soft IP throttle** | `429` / increasing latency keyed on source IP only | Yes — bypass via header/IP rotation (Phase 4) | |
| 54 | | **CAPTCHA injection** | `200` but body switches to a CAPTCHA challenge after N | Maybe — check if the verify endpoint enforces it server-side or if the API path skips it | |
| 55 | | **Silent shadow-throttle** | `200`/`401` returned for every request, but submissions are *dropped* — the genuinely-correct OTP/password stops being accepted, or responses become canned | **This is the trap.** A naive loop sees "all 200, no 429" and reports "no rate limit" — false. | |
| 56 | |
| 57 | **Shadow-throttle detector** — inject a known-good value at a known position and |
| 58 | confirm it still works under load: |
| 59 | ```bash |
| 60 | # Seed: position 500 in the brute set is the REAL OTP for your own test account. |
| 61 | # If the loop reaches 500 and the correct code no longer authenticates, |
| 62 | # th |