shuvonsec/claude-bug-bounty/credential-attack
Claude Code and agent skill by shuvonsec/claude-bug-bounty
- community
Checking that the SKILL.md file is still in the repository.
Password spray methodology for bug bounty — when to do it vs web-vuln hunting, the wordlist-gen + breach-check + osint-employees + spray pipeline, mode selection (http-form / oauth / o365 / okta), rate-limit + lockout tactics, BBP legal guardrails, success detection, and the spray → authenticated /hunt chain pattern. Use when assessing whether credential attack is worth running on a target, picking the right mode, or recovering from common pitfalls.
Install
npx vskill@latest install shuvonsec/claude-bug-bounty/credential-attackSKILL.md
CREDENTIAL ATTACK PIPELINE
Real-world initial-access vector. Verizon DBIR consistently ranks Stolen Credentials in the top 3 incident types. Most BB hunters skip this because they only try rockyou.txt and get rate-limited.
Core principle: humans pick lazy passwords. {CompanyName}{Year}!, {ProductName}{Season}, {City}123. Harvesting company-specific vocabulary (product names, office cities, internal project codes) before spraying is what makes the hit-rate go from 0.01% to 1%+.
This skill covers WHEN to use credential attack, HOW to chain the 4 commands, and the legal/operational guardrails.
WHEN TO RUN CREDENTIAL ATTACK
Credential attack is a parallel branch to /hunt, not a replacement. Both come after /recon:
Run it when:
- Target has a discoverable login endpoint (web form / O365 / Okta / OAuth)
- Program scope explicitly permits authentication testing or credential testing
- You can stomach a 30-min-to-multi-hour run (with conservative defaults)
Skip it when:
- Program policy lists "credential stuffing", "brute force", or "password attacks" as out-of-scope (this is the majority)
- Target only has SSO via a provider you don't control (e.g., "Login with Google")
- The login endpoint is rate-limited so aggressively that even 1 attempt/30min triggers alerts
KILL signals (don't even start):
- No login surface in recon output
- WAF (Cloudflare with Bot Management, Akamai) on every auth endpoint
- Program runs an active red-team — they'll see your spray immediately
- You don't have a clean wordlist yet (running rockyou.txt is a waste of lockouts)
THE 4-STAGE PIPELINE
You can run stages 1+2 in parallel with stage 3 (they share no inputs).
Stage 1 — /wordlist-gen <target>
Crawls the target website with cewler, deduplicates, applies hashcat rules to mutate (flexdemo → flexdemo!, Flexdemo, flexdemo123, flexdemo2025...).
Mode selection:
| Mode | Rules | When | |
|---|---|---|---|
minimal | top10_2025 (10 rules) | Cautious spray, paranoid program | |
balanced (default) | best66 (66 rules) | Standard — best signal/noise | |
aggressive | OneRuleToRuleThemAll (52k) | Offline cracking only, NOT spray (too many candidates) |
Filter selection:
| Filter | When | |
|---|---|---|
strict (default) | API-doc-heavy sites (Twilio, Stripe). Drops CSS hex colors, URL slugs, random API tokens that cewler harvests as "words" | |
loose | Marketing sites without API examples — keeps everything cewler found |
Output: recon/<target>/wordlists/ranked.txt — typically 50k-500k candidates depending on site size.
Stage 2 — /breach-check <wordlist>
Sends only first 5 chars of SHA-1 to HIBP (k-anonymity), enriches each password with its real-world breach count. Free, no API key, full passwords never leave your machine.
Breach-count interpretation:
| Range | Meaning | Spray strategy | |
|---|---|---|---|
| 0 | Never leaked | Could be company-specific OR truly random | |
| 1-1000 | "Sweet spot" — proven human use, not yet in every spray list | Prioritize | |
| 1k-1M | Mainstream | Usually already tried by previous attackers | |
| >1M | Generic (password, 123456) | Skip — every WAF expects these |
Standard filter for spray prep: --max-count 1000000 drops the boring generic stuff while keeping the sweet spot.
Performance: ~5 minutes for 10k passwords, ~50 minutes for 100k. Use --limit N --shuffle to sample if your wordlist is huge.
Stage 3 — /osint-employees <target>
theHarvester (search engines + CT logs) → derive names from email local-parts → username-anarchy permutations.
Default mode is conservative:
- Sources:
duckduckgo,brave,yahoo,mojeek,crtsh,certspotter,hackertarget,otx - No LinkedIn-specific scraping
- No paid OSINT (DeHashed, IntelX, Shodan)
Opt-in flags:
--with-linkedin— adds CrossLinked (Google/Bing dorks againstsite:linkedin.com). Read program policy first — some BBPs forbid employee identification.--with-pydictor-social— pydictor generates name-derived password candidates (john2025,john!2024).
Realistic expectations:
| Target type | Expected emails | Expected names | |
|---|---|---|---|
| US/EU SaaS (Twilio, Stripe) | 5-50 | depends — many CTOs are public | |
| State utility (Taipower, etc.) | 0 | 0 (no English-named LinkedIn profiles) | |
| Local SME | 0-10 | 0-5 |
For mature security-conscious targets, expect very few emails. The CT-log hostnames theHarvester finds are separate value — feed them back into /recon for more attack surface (this happened in our Taipower run: 0 emails but 59 new subdomains).
Stage 4 — /spray <login-url> --mode <mode>
The most dangerous command. Real auth attempts against live accounts. Read HARD GUARDS before running.
Mode selection:
| Mode | Use case | Engine | |
|---|---|---|---|
http-form | Custom login page (most BB targets) | Pure Python urllib | |
oauth | OAuth password grant (grant_type=password) | Pure Python urllib | |
o365 | Microsoft 365 / Azure AD | trevorspray | |
okta | Okta SSO | trevorspray |
Hard guards (no override possible without `--i-understand`):
- Typed-hostname confirmation — you must type the target hostname back. Defeats wrong-target slips.
- Lockout warning — calculates per-user failed-attempt count from
--passessize, warns if it exceeds typical thresholds. - Audit log JSONL — every attempt appended to
recon/<host>/spray/attempts-<ts>.jsonl. Passwords logged as SHA-256 prefix only, never plaintext. - Spray order —
pass[i] × all_usersper round. Each user sees at most 1 failed attempt per round, well under typical 5-10 lockout threshold.
HARD GUARDS — WHY THEY EXIST
Lockout policy reality check
Default rate-limit: --delay 1800 --jitter 60 (30 min/round + ±60s).
| Lockout policy (typical) | Threshold | Reset window | |
|---|---|---|---|
| Azure AD smart lockout | 10 failed in 10 min sliding | 10-min window | |
| Okta default | 10 in 10 min | configurable | |
| Custom apps | usually 5-10 per hour | varies wildly |
A spray with default delay tries 1 password per user per 30 min — keeps every user at 0 strikes within any sliding window.
`--aggressive` (60s/10s) is fast spray: use ONLY with explicit program permission. Against O365, it almost certainly triggers smart lockout.
Spray order — why pass[i] × all_users, NOT brute per-user
Our bughunter/tools/_spray_http_form.py and _spray_oauth.py enforce spray order.
SUCCESS DETECTION
http-form mode
Checked in this order:
--success-regex <body-regex>matches response → success--fail-regex <body-regex>set AND body does NOT match → success- HTTP redirect (3xx) to a path that is NOT the login page → success (heuristic)
- None of the above → not success
False positive risk: Without --success-regex or --fail-regex, heuristic 3 can mis-fire on sites that always redirect even on failure. Always supply `--fail-regex "Invalid|incorrect|wrong"` for production sprays.
oauth mode
- HTTP 200 with
"access_token"field in JSON body → success - HTTP 4xx (typically 400
invalid_grant/ 401) → fail
This is unambiguous; no regex needed.
o365 / okta (TREVORspray)
Output parsing. Less granular than our http-form / oauth handlers but well-tested upstream.
CHAIN PATTERN: SPRAY → AUTHENTICATED /HUNT
The real payout play:
The spray-only finding alone is usually rejected by mature BBPs (they treat it as "user's bad password choice, not our bug"). The chain is what pays.
Not yet wired in this branch: /hunt --authenticated-session <cookie> is a future PR. For now, after spray finds creds, manually feed the session into Burp / curl-based probing.
LEGAL GUARDRAILS
Before running /spray against ANY target, verify:
- Program policy explicitly allows credential testing. Look for keywords:
- ✅ "Credential testing permitted with rate-limit X"
- ✅ "Brute-force allowed against test accounts"
- ❌ "Credential stuffing", "brute force", "password attacks" listed under prohibited
- ⚠️ Silent — assume disallowed, ASK the program first
- The wordlist does not contain plaintext breach data. Using DeHashed-style plaintext passwords from real breaches to log into real accounts is illegal in most jurisdictions even with BB scope. HIBP hash-prefix is fine (we use this); plaintext breach corpus is not (we don't bundle this).
- Stop on first hit by default. Don't keep spraying after you have one valid set of creds — that's not testing, it's grinding for lulz.
--continue-on-hitexists but should only be used to evidence multiple users sharing a default password.
- Report the lockout impact. If your spray locked accounts, tell the program immediately with timestamps from the audit log. Don't make them discover it themselves.
COMMON PITFALLS (learned the hard way)
Pitfall 1 — Generic wordlist = no signal
/wordlist-gen with --filter loose against an API-heavy site gives you 500k candidates, 95% of which are CSS selectors, URL slugs, and example API tokens from docs.
Fix: Stick with the default --filter strict. Verified on Twilio: 56k loose → 34k strict (-39%), all noise dropped, real terms (flexdemo, webhook, programmable) preserved.
Pitfall 2 — --limit N biases the sample
The wordlist is sort -u'd alphabetically (ASCII order: digits < uppercase < lowercase). Naïve --limit 5000 samples ONLY digit/symbol-prefix entries.
Fix: Always use --shuffle when sampling. Verified on Twilio: without shuffle, top 5000 were 100% l33t variants (1nc0rr3t0, $m@rt...); with shuffle, you get representative coverage including a-z prefix candidates.
Pitfall 3 — {PASSWORD} vs {PASS} placeholder
Natural user instinct is --post-data "username={USER}&password={PASSWORD}". Our code accepts BOTH aliases ({USER}/{USERNAME} and {PASS}/{PASSWORD}). Unknown placeholders stay literal in the request — visible to you, not a crash.
Pitfall 4 — theHarvester silently writes JSON to cwd
theHarvester -f recon/<target>/osint/theharvester does NOT write to that path. It writes theharvester.json to $PWD (the directory you ran the command from).
Fix: bughunter/tools/osint_employees.sh wraps the call in (cd "$OUT_DIR" && theHarvester ... -f theharvester). If you invoke theHarvester directly, cd first.
Pitfall 5 — CrossLinked / theHarvester returning 0 emails
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/credential-attack/SKILL.md
Popularity
- Repository stars
- 4,237
- Repository forks
- 768
- 7-day trend score
- 42
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/shuvonsec/claude-bug-bounty/credential-attack)