{"slug":"hunt-subdomain","title":"hunt-subdomain","summary":"Hunting skill for subdomain takeover vulnerabilities. Includes modern provider fingerprints — Microsoft Azure DevOps `cloudapp.azure.com` regional-pool re-issue (1-click OAuth ATO via wildcard `reply_to`, Binary Security), Zendesk help-desk takeover → email interception → passwor","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-08-24T05:37:51.438192Z","repo":{"url":"https://github.com/elementalsouls/Claude-BugHunter","stars":4626,"forks":696,"license":"MIT","updatedAt":"2026-09-23T09:21:09Z"},"bodyHtml":"<hr>\n<h2>name: hunt-subdomain\ndescription: Hunting skill for subdomain takeover vulnerabilities. Includes modern provider fingerprints — Microsoft Azure DevOps <code>cloudapp.azure.com</code> regional-pool re-issue (1-click OAuth ATO via wildcard <code>reply_to</code>, Binary Security), Zendesk help-desk takeover → email interception → password reset chain (0xprial writeup), Vercel <code>cname.vercel-dns.com</code> deleted-project takeover, plus general Fastly CDN service re-attach and S3 dangling-bucket cookie-scope techniques. Use when hunting subdomain takeover — emphasis on ATO-chain primitives (OAuth <code>redirect_uri</code>, cookie-domain, email DNS).\nsources: github, hackerone_public, binarysecurity_research, can-i-take-over-xyz_research\nreport_count: 3</h2>\n<h2>Crown Jewel Targets</h2>\n<p>Subdomain takeover is high-value because it allows an attacker to serve content from a <strong>trusted, company-owned domain</strong> — bypassing browser same-origin trust, phishing filters, and user skepticism simultaneously.</p>\n<p><strong>Highest payout contexts:</strong></p>\n<ul>\n<li>Subdomains of major SaaS brands (Shopify, Snapchat, Mozilla, Yelp) where the trusted domain has user session context</li>\n<li>CDN-backed subdomains (Fastly, CloudFront) where CNAME points to unclaimed origins</li>\n<li>Third-party service integrations: UserVoice, WordPress.com, GitHub Pages, GitLab Pages, Heroku, Zendesk</li>\n<li>Preview/staging/dev subdomains (<code>new.</code>, <code>preview.</code>, <code>course.</code>, <code>delivery.</code>, <code>addons-preview.</code>) — abandoned after feature launches</li>\n<li>Subdomains used for OAuth redirect URIs or SSO endpoints — these pay highest</li>\n</ul>\n<p><strong>Asset types that matter most:</strong></p>\n<ul>\n<li>CNAME records pointing to deprovisioned third-party services</li>\n<li>NS delegations to abandoned zones</li>\n<li>A records pointing to unallocated cloud IPs (less common)</li>\n<li>GitLab/GitHub Pages with unclaimed project namespaces</li>\n</ul>\n<hr>\n<h2>Attack Surface Signals</h2>\n<p><strong>DNS signals:</strong></p>\n<ul>\n<li><code>CNAME</code> pointing to <code>*.github.io</code>, <code>*.gitlab.io</code>, <code>*.fastly.net</code>, <code>*.herokudns.com</code>, <code>*.wordpress.com</code>, <code>*.uservoice.com</code>, <code>*.zendesk.com</code>, <code>*.s3.amazonaws.com</code>, <code>*.azurewebsites.net</code>, <code>*.netlify.app</code></li>\n<li>NXDOMAIN or <code>SERVFAIL</code> on the CNAME target while the parent record still exists</li>\n<li>NS records delegating to registrars where the zone is no longer registered</li>\n</ul>\n<p><strong>HTTP response signals:</strong></p>\n<ul>\n<li><code>\"There isn't a GitHub Pages site here\"</code></li>\n<li><code>\"NoSuchBucket\"</code> (S3)</li>\n<li><code>\"The specified bucket does not exist\"</code></li>\n<li><code>\"No such app\"</code> (Heroku)</li>\n<li><code>\"Sorry, this shop is currently unavailable\"</code> (Shopify)</li>\n<li><code>\"This UserVoice subdomain is available\"</code></li>\n<li><code>\"Do you want to register\"</code> (any domain parking page)</li>\n<li>HTTP 404 with provider-specific error templates</li>\n<li>Fastly: <code>\"Fastly error: unknown domain\"</code></li>\n<li><code>\"404 Web Site not found\"</code> (Azure App Service)</li>\n</ul>\n<p><strong>Tech stack signals:</strong></p>\n<ul>\n<li>Response headers: <code>X-Served-By: cache-*</code> (Fastly), <code>X-GitHub-Request-Id</code>, <code>Server: Netlify</code></li>\n<li><code>CNAME</code> chain resolving to provider infrastructure but returning provider 404</li>\n<li>SSL cert issued to provider wildcard (<code>*.fastly.net</code>) rather than company domain</li>\n</ul>\n<hr>\n<h2>Step-by-Step Hunting Methodology</h2>\n<ol>\n<li><p><strong>Enumerate all subdomains</strong> for the target using passive + active sources:</p>\n<ul>\n<li><code>subfinder -d target.com -all</code></li>\n<li><code>amass enum -passive -d target.com</code></li>\n<li><code>assetfinder --subs-only target.com</code></li>\n<li>Certificate transparency: <code>crt.sh/?q=%.target.com</code></li>\n</ul>\n</li>\n<li><p><strong>Resolve all subdomains</strong> and flag those with:</p>\n<ul>\n<li>NXDOMAIN responses</li>\n<li>CNAME pointing to a third-party provider</li>\n</ul>\n<pre><code>cat subdomains.txt | dnsx -a -cname -o resolved.txt\n</code></pre>\n</li>\n<li><p><strong>Cross-reference CNAMEs</strong> against known vulnerable provider fingerprints using <code>nuclei</code> or <code>subjack</code>:</p>\n<pre><code>subjack -w subdomains.txt -t 100 -timeout 30 -ssl -c fingerprints.json\nnuclei -l subdomains.txt -t takeovers/\n</code></pre>\n</li>\n<li><p><strong>Manual verification</strong> for each flagged subdomain:</p>\n<ul>\n<li><code>dig CNAME subdomain.target.com</code> — confirm CNAME exists</li>\n<li><code>dig A &lt;cname-target&gt;</code> — confirm NXDOMAIN or no resolution</li>\n<li><code>curl -sk https://subdomain.target.com</code> — check for provider error string</li>\n</ul>\n</li>\n<li><p><strong>Confirm claimability</strong> — attempt to register the resource:</p>\n<ul>\n<li>GitHub Pages: check if <code>&lt;username&gt;.github.io/&lt;repo&gt;</code> or org page is unclaimed</li>\n<li>GitLab Pages: check project namespace</li>\n<li>S3: attempt <code>aws s3api create-bucket --bucket &lt;bucketname&gt;</code></li>\n<li>UserVoice/Zendesk/WordPress: visit registration URL</li>\n<li>Fastly: check if origin hostname is unregistered</li>\n</ul>\n</li>\n<li><p><strong>Claim the resource</strong> (only enough to prove control — do NOT serve malicious content):</p>\n<ul>\n<li>Create a minimal index page with your HackerOne username and a timestamp</li>\n<li>Take screenshot showing your content served on <code>subdomain.target.com</code></li>\n</ul>\n</li>\n<li><p><strong>Document the chain</strong>: CNAME record → provider target → unclaimed resource → your content</p>\n</li>\n<li><p><strong>Assess impact escalation</strong>:</p>\n<ul>\n<li>Does the subdomain appear in OAuth redirect allowlists?</li>\n<li>Does it share cookies with parent domain (<code>domain=.target.com</code>)?</li>\n<li>Is it referenced in the app's CSP?</li>\n<li>Can it receive authenticated API calls?</li>\n</ul>\n</li>\n<li><p><strong>Write report</strong> before releasing the claim (some programs want to verify first)</p>\n</li>\n</ol>\n<hr>\n<h2>Payload &amp; Detection Patterns</h2>\n<p><strong>Bulk CNAME extraction and NXDOMAIN detection:</strong></p>\n<pre><code># Extract CNAMEs and check if target resolves\nwhile read sub; do\n  cname=$(dig +short CNAME \"$sub\" | head -1)\n  if [ -n \"$cname\" ]; then\n    result=$(dig +short A \"$cname\")\n    if [ -z \"$result\" ]; then\n      echo \"[POTENTIAL] $sub -&gt; $cname (NXDOMAIN)\"\n    fi\n  fi\ndone &lt; subdomains.txt\n</code></pre>\n<p><strong>Nuclei takeover scan:</strong></p>\n<pre><code>nuclei -l subdomains.txt -t ~/nuclei-templates/http/takeovers/ -severity medium,high,critical\n</code></pre>\n<p><strong>subjack with SSL:</strong></p>\n<pre><code>subjack -w subdomains.txt -t 100 -timeout 30 -ssl -c $GOPATH/src/github.com/haccer/subjack/fingerprints.json -v\n</code></pre>\n<p><strong>Provider fingerprint grep patterns:</strong></p>\n<pre><code>curl -sk \"https://$subdomain\" | grep -iE \\\n  \"there isn't a github pages|no such bucket|no such app|this uservoice|fastly error: unknown domain|do you want to register|sorry, this shop|project not found|404 not found|unclaimed\"\n</code></pre>\n<p><strong>Check if subdomain is in scope for cookies (shared parent domain):</strong></p>\n<pre><code>curl -Isk \"https://target.com\" | grep -i \"set-cookie\" | grep \"domain=.target.com\"\n</code></pre>\n<p><strong>Fastly-specific detection:</strong></p>\n<pre><code>curl -sI \"https://subdomain.target.com\" -H \"Host: subdomain.target.com\" | grep -i \"fastly\\|x-served-by\\|x-cache\"\ncurl -sk \"https://subdomain.target.com\" | grep -i \"fastly error\"\n</code></pre>\n<p><strong>S3 unclaimed bucket check:</strong></p>\n<pre><code>aws s3api head-bucket --bucket &lt;extracted-bucket-name&gt; 2&gt;&amp;1 | grep -i \"NoSuchBucket\\|403\\|404\"\n</code></pre>\n<p><strong>GitLab Pages specific:</strong></p>\n<pre><code>dig CNAME sub.target.com\n# If pointing to *.gitlab.io — visit the gitlab.io URL directly\n# 404 from gitlab.io project = claimable\n</code></pre>\n<hr>\n<h2>Common Root Causes</h2>\n<ol>\n<li><p><strong>Service offboarding without DNS cleanup</strong> — Developer removes a Heroku app, UserVoice account, or WordPress site but never deletes the CNAME record. DNS lives forever; service does not.</p>\n</li>\n<li><p><strong>Staging/preview infrastructure abandoned post-launch</strong> — <code>course.</code>, <code>new.</code>, <code>preview.</code>, <code>beta.</code> subdomains provisioned for a product launch, pointed at a third-party, then forgotten when the campaign ends.</p>\n</li>\n<li><p><strong>Subdomain provisioned by a third-party team</strong> — Marketing sets up a UserVoice or Zendesk subdomain via IT, product sunset kills it, but DNS is owned by engineering who doesn't know.</p>\n</li>\n<li><p><strong>CDN misconfiguration without origin validation</strong> — Fastly and similar CDNs historically allowed any domain to \"claim\" a backend hostname by creating a service pointing to it. Unregistered origin hostnames become claimable.</p>\n</li>\n<li><p><strong>GitHub/GitLab Pages namespace not reserved</strong> — Organization renames, user accounts deleted, or repos made private/deleted while the Pages CNAME still points to the old namespace.</p>\n</li>\n<li><p><strong>Wildcard DNS entries</strong> — <code>*.target.com</code> pointing to a cloud provider means <em>any</em> unclaimed subdomain potentially resolves to claimable infrastructure.</p>\n</li>\n<li><p><strong>Acquired/divested company DNS not cleaned</strong> — Post-acquisition, former brand subdomains (like <code>oberlo.com</code> under Shopify) retain CNAMEs to services that are no longer paid for.</p>\n</li>\n</ol>\n<hr>\n<h2>Bypass Techniques</h2>\n<p><strong>Defense: Manual fingerprint review before publishing</strong></p>\n<ul>\n<li>Bypass: Use alternative error strings — providers change their 404 pages. Maintain an up-to-date fingerprint list. Some providers show <em>different</em> errors on HTTP vs HTTPS. Test both.</li>\n</ul>\n<p><strong>Defense: Scope restrictions (only main domain in scope)</strong></p>\n<ul>\n<li>Bypass: Check program's asset list carefully — <code>*.target.com</code> wildcards often include subdomains implicitly. Escalate impact to get it in scope.</li>\n</ul>\n<p><strong>Defense: \"Can't reproduce\" responses due to timing</strong></p>\n<ul>\n<li>Bypass: Screenshot immediately after claiming. Record a video walkthrough. The window can be short for popular subdomains.</li>\n</ul>\n<p><strong>Defense: HTTPS certificate mismatch blocking proof</strong></p>\n<ul>\n<li>Bypass: Some providers (GitHub Pages, Netlify) auto-provision TLS for claimed domains. Others don't — show HTTP takeover and note TLS would be resolved by provider on claim.</li>\n</ul>\n<p><strong>Defense: Provider-side validation (Fastly verifying domain ownership)</strong></p>\n<ul>\n<li>Bypass: Some Fastly configurations don't validate origin hostnames. Check if the CNAME target is a generic Fastly backend hostname vs. a customer-verified one. Try claiming anyway and observe behavior.</li>\n</ul>\n<p><strong>Defense: Rate limiting on subdomain enumeration</strong></p>\n<ul>\n<li>Bypass: Use passive-only sources (SecurityTrails, Shodan, crt.sh, VirusTotal) to avoid triggering WAF/IDS. DNS resolution doesn't touch the web server.</li>\n</ul>\n<p><strong>Defense: Program claims \"low severity / no impact\"</strong></p>\n<ul>\n<li>Bypass: Demonstrate same-origin cookie theft, OAuth redirect abuse, or CSP bypass to escalate. Find if the subdomain is listed in any <code>postMessage</code> <code>targetOrigin</code> checks in JS.</li>\n</ul>\n<hr>\n<h2>Gate 0 Validation</h2>\n<ol>\n<li><p><strong>What can the attacker DO right now?</strong>\nCan you register the unclaimed resource (GitHub repo, S3 bucket, Heroku app, UserVoice account) and serve arbitrary content — including phishing pages, credential harvesters, or malicious scripts — under the target's trusted domain name?</p>\n</li>\n<li><p><strong>What does the victim LOSE?</strong>\nUsers lose trust and safety: they see a company-branded URL serving attacker content. The company loses brand integrity, potentially leaks session cookies if the subdomain is in <code>domain=.target.com</code> scope, and may have OAuth/SSO flows hijacked. Depending on CSP configuration, XSS against the main application may be possible.</p>\n</li>\n<li><p><strong>Can it be reproduced in 10 minutes from scratch?</strong></p>\n<ul>\n<li><code>dig CNAME subdomain.target.com</code> → confirms CNAME to provider</li>\n<li><code>curl -sk https://subdomain.target.com</code> → confirms provider error string</li>\n<li>Visit provider registration page → confirms namespace is available</li>\n<li>Screenshots of all three steps = reproducible in under 10 minutes</li>\n</ul>\n</li>\n</ol>\n<p>If you cannot show the provider resource is <em>currently unclaimed and claimable</em>, it is not a valid report.</p>\n<hr>\n<h2>Real Impact Examples</h2>\n<p><strong>Scenario A — Trusted Brand Phishing via Abandoned SaaS (Snapchat/UserVoice)</strong>\nAn attacker finds <code>feedback.snapchat.com</code> CNAME pointing to a UserVoice subdomain. The UserVoice account was cancelled but the DNS record remained. The attacker registers the matching UserVoice subdomain for free, gaining control of <code>feedback.snapchat.com</code>. Any user navigating to that URL — perhaps from old bookmarks or Google results — sees attacker-controlled content on a Snapchat-branded domain. Since the domain is trusted by browsers, phishing campaigns sent from this subdomain bypass email security filters that check domain reputation.</p>\n<p><strong>Scenario B — CDN Origin Takeover Enabling Same-Origin Attacks (Mozilla/Fastly)</strong>\n<code>addons-preview-cdn.mozilla.net</code> had a CNAME pointing to a Fastly origin hostname that was no longer registered to Mozilla's Fastly account. An attacker could create a Fastly service claiming that origin hostname, causing all requests to <code>addons-preview-cdn.mozilla.net</code> to be routed to attacker-controlled Fastly infrastructure. Since the subdomain shares the <code>mozilla.net</code> domain, it could be leveraged to serve malicious CDN assets that appear to come from Mozilla's infrastructure, potentially bypassing CSP rules that allowlist <code>*.mozilla.net</code>.</p>\n<p><strong>Scenario C — Staging Subdomain Abandoned Post-Product Migration (Rails/GitHub Pages)</strong>\n<code>new.rubyonrails.org</code> was pointed at a GitHub Pages deployment for a website redesign project. After the new site launched and the old GitHub repo was deleted or made private, the DNS CNAME remained. An attacker could fork or create a matching GitHub Pages repository and claim the namespace, serving content under <code>new.rubyonrails.org</code>. Because this is the official Ruby on Rails domain, any content served there — including fake download links or malicious gems — carries the full trust of the Rails brand.</p>\n<hr>\n<h2>Disclosed Report Citations (2022-2023)</h2>\n<p>The following coordinated-disclosure / writeup cases extend this skill with <strong>modern provider fingerprints</strong> (Vercel/Azure cloudapp/Zendesk era) and explicit ATO-chain examples. Citations #12 and #13 are external writeups (not disclosed HackerOne reports) — treat their payout figures as unverified; only #14 has a public H1 report ID.</p>\n<ol start=\"12\">\n<li><p><strong>Microsoft Azure DevOps — Two <code>cloudapp.azure.com</code> subdomains + wildcard <code>*.visualstudio.com</code> OAuth reply_to → 1-click ATO</strong> (<a href=\"https://www.binarysecurity.no/posts/2022/11/azure-devops-takeover\">Binary Security writeup</a>)</p>\n<ul>\n<li>Subclass: Azure <code>cloudapp.azure.com</code> regional-pool dangling CNAME — chained to ATO</li>\n<li>ATO chain: <strong>YES</strong> — <code>app.vssps.visualstudio.com/_signin?reply_to=https://feedsprodwcus0dr.feeds.visualstudio.com/</code> whitelisted any <code>*.visualstudio.com</code>. Attacker claimed the dangling Azure VM hostnames, then crafted sign-in URLs that returned JWT + FedAuth tokens to attacker-controlled endpoints</li>\n<li>Claim flow: identify dangling <code>cloudapp.azure.com</code> CNAME, deploy a free-tier VM in the same Azure region requesting the exact released hostname, Azure re-issues the name first-come-first-serve</li>\n<li>Year: reported Feb 2021, disclosed Nov 2022 — MSRC explicitly out-of-scope (relied on subdomain takeover), $0</li>\n</ul>\n</li>\n<li><p><strong>Anonymous H1 — <code>admin-support.xyz.com</code> → unclaimed Zendesk → email interception → ATO</strong> (<a href=\"https://0xprial.com/the-art-of-zendesk-hijacking/\">Writeup by 0xprial</a>)</p>\n<ul>\n<li>Subclass: Zendesk help-desk takeover via <code>xyzdocs.zendesk.com</code> host-mapping</li>\n<li>ATO chain: <strong>YES</strong> — researcher configured email forwarding on the hijacked Zendesk instance, intercepted <code>support@xyz.com</code> tickets containing payment info + password-reset emails, then triggered password resets on customer accounts that delivered reset links into the attacker's Zendesk inbox</li>\n<li>Claim flow: <code>dig CNAME</code> returns <code>xyzdocs.zendesk.com</code> (unregistered) → register free Zendesk trial → add <code>xyzdocs</code> as subdomain → enable host-mapping for <code>admin-support.xyz.com</code></li>\n<li>Year: 2023 — payout per the 0xprial writeup (blog source; no public HackerOne report ID, treat as unverified)</li>\n</ul>\n</li>\n<li><p><strong>Vercel deleted-project takeover</strong> — a dangling <code>cname.vercel-dns.com</code> CNAME pointing to a removed Vercel project can be re-claimed by deploying a new project under that name.</p>\n<ul>\n<li>Subclass: Vercel dangling CNAME (<code>cname.vercel-dns.com</code>) after project deletion</li>\n<li>Impact: crypto-DEX phishing — <code>proxies.</code> subdomain trusted for RPC proxy routing; attacker could serve malicious wallet-drain JS under a \"trusted\" subdomain</li>\n<li>Claim flow: subdomain returns Vercel 404 <code>DEPLOYMENT_NOT_FOUND</code> → create free Vercel project → Settings → Domains → add <code>proxies.sifchain.finance</code> — Vercel verifies the existing CNAME and auto-issues TLS without out-of-band ownership proof</li>\n<li>Year: 2022 — Sifchain treated as Critical (web3 phishing vector)</li>\n</ul>\n</li>\n</ol>\n<p><strong>Fastly CDN dangling-service technique (general, not a single disclosed report):</strong></p>\n<ul>\n<li>Fingerprint: subdomain returns <code>Fastly error: unknown domain. Please check that this domain has been added to a service</code></li>\n<li>Claim flow: sign up for Fastly free trial → create new CDN service → attach the dangling hostname as the service domain</li>\n<li>Root cause: Fastly historically does not verify CNAME ownership on service-creation; any CNAME pointing into Fastly's anycast can be attached to a fresh service</li>\n<li>Potential ATO chain: chains to CSP-bypass + JS-injection if the parent domain trusts the <code>assets.</code>/CDN host for <code>script-src</code></li>\n</ul>\n<hr>\n<h2>Chains &amp; Compositions (Senior Hunting)</h2>\n<p>Subdomain takeover by itself is Low-Medium / Informational on most mature programs — defacement of a non-business-critical subdomain is unsexy. The chain payout is 10-100x the standalone. <strong>Every takeover should be evaluated against the five chains below before submission.</strong> If none apply, you have a Low; if one applies, you have a High; if two compose, you have a Critical.</p>\n<h3>Chain 1 — Takeover + OAuth <code>redirect_uri</code> Whitelist → Auth-Code Theft → 1-Click ATO</h3>\n<ul>\n<li><strong>A.</strong> Enumerate the OAuth <code>redirect_uri</code> allowlist via <code>/oauth/authorize</code> flow. Look for any wildcard <code>*.target.com</code> or any takeover-candidate hostname in the static list (e.g., <code>feedsprod.feeds.visualstudio.com</code>, <code>legacy.target.com</code>).</li>\n<li><strong>B.</strong> Find a takeover-able subdomain in that allowlist. Claim it via the provider's onboarding (Vercel project, Azure cloudapp regional pool, S3 bucket, Heroku app, Zendesk, Shopify storefront — see the Disclosed Report Citations above).</li>\n<li><strong>C.</strong> Host an OAuth callback receiver on the claimed subdomain. Send victim to <code>/oauth/authorize?redirect_uri=https://legacy.target.com/cb&amp;response_type=code&amp;client_id=&lt;legit&gt;</code>. Victim's browser already has session → auth happens transparently → auth code lands on attacker host. Exchange via token endpoint → ATO.</li>\n<li><strong>Impact:</strong> Persistent 1-click ATO across every user of the target. OAuth flow is implicit-to-the-user (no consent screen if previously consented), so requires only a single click on attacker's link.</li>\n<li><strong>Real shape:</strong> Microsoft Azure DevOps <code>cloudapp.azure.com</code> + wildcard <code>*.visualstudio.com</code> reply_to chain (Binary Security, Nov 2022 — Disclosed Report Citation #12). Multiple H1 disclosures on SaaS programs with permissive OAuth allowlists.</li>\n</ul>\n<h3>Chain 2 — Takeover at Sibling Subdomain + Cookie-Domain Wildcard → Session Fixation on Parent App</h3>\n<ul>\n<li><strong>A.</strong> Inspect cookies set by the main app (<code>app.target.com</code>). If <code>Set-Cookie</code> has <code>Domain=.target.com</code> (parent-scoped) instead of host-only, cookies bleed to every sibling subdomain — including taken-over ones.</li>\n<li><strong>B.</strong> Take over any sibling (<code>legacy.target.com</code>, <code>feedback.target.com</code>, <code>assets.target.com</code>). The taken-over host can now <code>Set-Cookie</code> for the parent domain.</li>\n<li><strong>C.</strong> Plant <code>Set-Cookie: SESSIONID=&lt;attacker_session&gt;; Domain=.target.com</code> via a script on the taken-over host. Victim visits <code>app.target.com</code> with attacker's session cookie attached. Server treats them as the attacker's account → session-fixation ATO.</li>\n<li><strong>Impact:</strong> ATO without OAuth or password reset — pure cookie-domain bleed. Especially effective when the parent app uses a non-<code>__Host-</code> prefixed session cookie.</li>\n<li><strong>Real shape:</strong> Discussed extensively in <code>hunt-auth-bypass</code> Duende BFF Attack Class 2 (cookie-domain wildcarding turns subdomain takeover into session fixation). Pattern class: S3-bucket-takeover combined with parent-scoped (<code>Domain=.target.com</code>) cookies.</li>\n</ul>\n<h3>Chain 3 — Takeover + CSP <code>script-src</code> Includes the Taken-Over Host → Persistent Stored XSS on Main App</h3>\n<ul>\n<li><strong>A.</strong> Inspect CSP header on the main app's HTML response. Look for <code>script-src 'self' assets.target.com cdn.target.com legacy.target.com ...</code>.</li>\n<li><strong>B.</strong> Take over one of the CSP-allowlisted subdomains (especially common: stale CNAMEs to deleted CDNs, deleted Vercel/Netlify projects, archived analytics services).</li>\n<li><strong>C.</strong> Host attacker-controlled JavaScript at the takeover host. Every page load on the main app fetches <code>&lt;script src=\"//taken-over-host/x.js\"&gt;</code> because the host is on the CSP allowlist. JS executes with main-app origin — full session access, can call any same-origin API.</li>\n<li><strong>Impact:</strong> Stored XSS-equivalent on every page of the main app, persistent until the CSP is updated. Bypasses every input sanitiser because the JS source is \"trusted\" per CSP.</li>\n<li><strong>Real shape:</strong> Sifchain <code>proxies.sifchain.finance</code> Vercel takeover — Disclosed Report Citation #14 (web3 phishing); pattern documented in multiple H1 disclosures 2020-2024.</li>\n</ul>\n<h3>Chain 4 — Takeover + CORS <code>Access-Control-Allow-Origin</code> Regex Match → Credentialed Cross-Origin API Read</h3>\n<ul>\n<li><strong>A.</strong> Inspect the API's CORS configuration. Look for any regex / wildcard / suffix-match in <code>Access-Control-Allow-Origin</code> that includes <code>*.target.com</code> or <code>target.com.*</code> (the second is a common bug).</li>\n<li><strong>B.</strong> Take over any subdomain that the CORS regex would accept (or register a new <code>target.com.attacker.com</code> host if suffix-match is broken).</li>\n<li><strong>C.</strong> Attacker page hosted on the taken-over subdomain issues <code>fetch('https://api.target.com/account', {credentials:'include'})</code>. CORS preflight passes. Server returns credentialed response. Attacker's JS reads it.</li>\n<li><strong>Impact:</strong> Mass cross-tenant API read with credentials — sessions, PATs, account data, billing records — all reachable from a single attacker page.</li>\n<li><strong>Real shape:</strong> Multiple disclosed cases; cross-refs <code>hunt-api-misconfig</code> CORS subsection. Pairs with <code>hunt-misc</code> step 1 (CORS regex enumeration).</li>\n</ul>\n<h3>Chain 5 — Takeover at Email DNS (DKIM / SPF / MX) → Email Spoofing → Phishing Trusted by Parent Brand</h3>\n<ul>\n<li><strong>A.</strong> Enumerate the target's email DNS — DKIM selectors (<code>selector1._domainkey.target.com</code>), SPF includes (<code>include:_spf.takeover-candidate.com</code>), MX records (<code>mx.target.com → defunct-provider.example</code>).</li>\n<li><strong>B.</strong> Take over any DKIM-selector or SPF-include host. Now the attacker can publish DKIM/SPF records that authorise their own server to send mail \"from\" <code>@target.com</code>.</li>\n<li><strong>C.</strong> Send phishing email <code>From: support@target.com</code> to victim. Recipient mail server passes SPF + DKIM checks (because the takeover server is now authorised). Email lands in inbox with <code>target.com</code> brand, no security warning.</li>\n<li><strong>Impact:</strong> Highly-effective phishing campaign exploiting the parent brand. Victims trust the email because every authentication check passes. Credential harvesting, BEC fraud, supply-chain access.</li>\n<li><strong>Real shape:</strong> Multiple historical disclosures on DKIM selector takeover / SPF include chain hijacking. Cross-refs DMARC / SPF / DKIM section in <code>offensive-osint</code>.</li>\n</ul>\n<h3>Operator-level pattern</h3>\n<p>The five chains above are exhaustive in practice — virtually every senior-tier subdomain-takeover payout maps to one of them. Before reporting any takeover, run through the checklist:</p>\n<ol>\n<li><strong>OAuth <code>redirect_uri</code> allowlist</strong> — does the taken-over host appear? → Chain 1, Critical.</li>\n<li><strong>Parent-domain cookies</strong> — does the main app set <code>Domain=.target.com</code>? → Chain 2, High.</li>\n<li><strong>CSP <code>script-src</code></strong> — does the taken-over host appear in the allowlist? → Chain 3, Critical.</li>\n<li><strong>CORS allowlist</strong> — does any regex match the taken-over host? → Chain 4, High.</li>\n<li><strong>Email DNS (DKIM selector / SPF include)</strong> — does the taken-over host appear? → Chain 5, High.</li>\n</ol>\n<p>If none apply, file at Low/Informational. <strong>Do not file at Critical without demonstrating one of these chains</strong> — triagers downgrade fast otherwise.</p>\n<p>Cross-references:</p>\n<ul>\n<li><code>hunt-oauth</code> — Chain 1 (<code>redirect_uri</code> bypass class)</li>\n<li><code>hunt-auth-bypass</code> Duende BFF Attack Class 2 — Chain 2 (cookie scoping)</li>\n<li><code>hunt-xss</code> Chain 4 — Chain 3 (CSP bypass via trusted-origin JS)</li>\n<li><code>hunt-api-misconfig</code> CORS section — Chain 4</li>\n<li><code>offensive-osint</code> email-security section — Chain 5</li>\n</ul>\n<hr>\n<h2>Related Skills &amp; Chains</h2>\n<ul>\n<li><strong><code>hunt-cloud-misconfig</code></strong> — Most stale CNAMEs point at deleted cloud assets (S3, CloudFront, Heroku). Chain primitive: Cloud misconfig (S3 deleted) + <code>hunt-subdomain</code> → unclaimed CNAME points to bucket → claim bucket name → full subdomain control.</li>\n<li><strong><code>hunt-oauth</code></strong> — A takeover on an OAuth <code>redirect_uri</code> host = persistent ATO across the entire SSO surface. Chain primitive: Subdomain takeover at <code>auth.target.com</code> + OAuth redirect_uri allowlist → auth code theft → ATO every user that re-authenticates.</li>\n<li><strong><code>hunt-api-misconfig</code></strong> — CORS regexes routinely allowlist a takeoverable subdomain. Chain primitive: Subdomain takeover + CORS <code>*.target.com</code> with credentials → credentialed cross-origin API read → mass IDOR.</li>\n<li><strong><code>hunt-xss</code></strong> — A claimed subdomain is same-origin to session-cookie-domain siblings. Chain primitive: Subdomain takeover at <code>feedback.target.com</code> + cookie scope <code>.target.com</code> → JS hosted on takeover host reads main-app cookies → session hijack.</li>\n<li><strong><code>security-arsenal</code></strong> — Load the 27+ Subdomain Takeover Fingerprint Table (NoSuchBucket, \"no such app\", GitHub Pages 404 strings, Heroku, Shopify, Fastly) and the <code>subzy</code>/<code>subjack</code> automation patterns.</li>\n<li><strong><code>triage-validation</code></strong> — Apply the Unique-Marker gate: takeover claim is informational on its own; submit only after publishing a unique HTML marker on the claimed host AND demonstrating a downstream impact (cookie read, OAuth chain, CSP bypass).</li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":25030,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-08-24T05:44:20.308985Z","sha256":"0F8FDA3A3422DB35816DE4D09242EA1B6FD5A62DD8BED2490DB06F4A64ED92FA","sizeBytes":9824},"review":null,"source":{"repositoryUrl":"https://github.com/elementalsouls/Claude-BugHunter","path":"skills/hunt-subdomain","license":"MIT","commit":"4d7b4cdfddb7ec67fba87821e54c768248a544bd","subtreeSha":"AEF6B21BE86F53C8F6A9237A6B9BE060AC4877F233E9A138D365E4743ECF5B8F","lastSyncedAt":"2026-09-24T06:49:51.293025Z"},"reviewedAt":"2026-08-24T05:59:43.407615Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/elementalsouls/Claude-BugHunter/tree/main/skills/hunt-subdomain"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install elementalsouls-claude-bughunter@llmmart"},{"target":"git","command":"git clone https://github.com/elementalsouls/Claude-BugHunter.git"}]}