--- name: hunt-csrf description: Hunting skill for csrf vulnerabilities. category: security risk: offensive source: https://github.com/elementalsouls/Claude-BugHunter source_repo: elementalsouls/Claude-BugHunter source_type: community date_added: '2026-09-20' license: MIT license_source: https://github.com/elementalsouls/Claude-BugHunter/blob/main/LICENSE compatibility: Requires explicit written authorization for a target scope plus the relevant testing tools for this technique. Docs-only; helper scripts and commands not bundled. sources: github, hackerone_public, bugcrowd_public, github_security_advisories report_count: 18 --- > **⚠️ AUTHORIZED USE ONLY** > This skill is for educational purposes or authorized security assessments only. > You must have explicit, written permission from the system owner before using this tool. > Misuse of this tool is illegal and strictly prohibited. > **Mandatory confirmation gate** > Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target: > 1. Ask the user to state the exact target URL, IP, account, or resource. > 2. Ask the user to confirm written authorization and the permitted scope. > 3. Show the exact command(s) and explain their expected effect. > 4. Wait for explicit confirmation in the current conversation. > > Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab. ## Browser delivery is required for confirmation Raw clients can vary headers to diagnose checks, but can spoof values a browser cannot send. Success with an authenticated cookie and forged Origin is not CSRF evidence. Confirm a harmless reversible state change using a real supported browser, separate controlled origin and test accounts, documenting cookies, SameSite, preflight, redirects and actual before/after state. Never transfer money or alter real users as a demonstration. ## Autonomous Testing Priority **CSRF only matters on state-changing actions that a browser could be tricked into making cross-site.** **Testing flow:** 1. **GET the form endpoint** to establish a baseline and check what fields exist (look for hidden `csrf_token`, `authenticity_token`, `_token`, `csrfmiddlewaretoken` fields). 2. **POST the state-changing action without any CSRF token field.** Send only the functional parameters (email, amount, etc.). 3. **Use a "simple-request" Content-Type** — `application/x-www-form-urlencoded`, `multipart/form-data`, OR `text/plain` are the three CORS "simple" content-types a cross-origin form can send with no preflight. A JSON endpoint is CSRF-resistant **only if the server rejects those** — if it also accepts a `text/plain` body (common), craft a `text/plain` payload that parses as valid JSON (see the JSON-CSRF-via-text/plain section). Don't skip a JSON endpoint on the assumption that `application/json` alone is protective. 4. **A successful raw replay is only a candidate. Confirm browser-deliverable credentials and the actual state change.** **High-value targets (in order of impact):** - Email/password change → account takeover - Money transfer or payment → financial fraud - Admin actions (role assignment, user deletion) - OAuth social-account linking → persistent ATO **Token bypass techniques when a token IS present:** - Omit the token field entirely — some frameworks only validate if the field exists, not if it's absent - Send an empty value (`_token=`) — some validate format, not presence - Copy a token from another session — some tokens aren't tied to the session **Scope:** Login CSRF can have impact and belongs in an authorized assessment; evaluate logout by concrete harm. GET endpoints can also mutate state. Exclude only genuinely read-only behavior. --- ## Crown Jewel Targets CSRF becomes high-value when it touches **state-changing actions with account-level or financial consequences**. The highest-paying targets are: - **Account takeover vectors**: OAuth/SSO flows (RelayState manipulation), social account linking/unlinking (Oculus-Facebook, SocialClub), import-friends features that expose OAuth tokens - **Authentication infrastructure**: Login CSRF, session fixation via CSRF, forced account association - **API endpoints accepting cross-origin POST**: JSON APIs, heartbeat/activity APIs, anything that skips Content-Type enforcement - **Third-party integrations**: Grafana, monitoring dashboards, embedded analytics — often lag on CSRF protections - **Social platforms**: Twitter/X collections, friend imports, social graph mutations — high-volume, authenticated actions with real user impact **Asset types that pay most:** Core product auth flows > API gateways > third-party integrations running on subdomains > admin panels. --- ## Attack Surface Signals ### URL Patterns ``` /oauth/authorize?RelayState= /accounts/link /import/friends /api/v*/heartbeat /api/v*/collect /monitoring/* (Grafana, Prow, Prometheus) /auth/saml/callback /connect/* (social integrations) ``` ### Response Header Signals ``` # Missing or weak SameSite cookie attributes Set-Cookie: session=abc123; HttpOnly # inspect browser default and delivery; absence alone is not proof Set-Cookie: session=abc123; SameSite=None # explicitly allows cross-site # Missing CSRF headers # No X-Frame-Options or permissive CORS Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true # wildcard origin cannot authorize credentialed CORS in browsers ``` ### JS / DOM Patterns ```javascript // Static or predictable CSRF tokens meta[name="csrf-token"] // grep if value changes across sessions authenticity_token // Rails — check if reused across page loads // JSON endpoints without Content-Type enforcement fetch('/api/heartbeat', {method: 'POST', body: JSON.stringify(data)}) // No CSRF token in form at all
``` ### JSON CSRF via text/plain (bypasses Content-Type check) ```html ``` ### curl: Test CSRF token omission ```bash # Capture a valid request, then replay without token curl -s -X POST https://target.com/settings/email \ -H "Cookie: session=YOUR_SESSION" \ -d "email=attacker@evil.com" \ -v 2>&1 | grep -E "HTTP|location|error" ``` ### curl: Test token reuse across sessions ```bash # Get token from session A TOKEN_A=$(curl -s https://target.com/settings -H "Cookie: session=SESSION_A" \ | grep -oP 'authenticity_token[^"]*value="\K[^"]+') # Use token A in session B's request curl -s -X POST https://target.com/settings/update \ -H "Cookie: session=SESSION_B" \ -d "authenticity_token=$TOKEN_A&email=test@test.com" \ -v ``` ### Grep patterns for recon ```bash # Find CSRF token fields in HTML responses grep -Eo 'name="(csrf|_token|authenticity_token|csrfmiddlewaretoken)"[^>]*value="[^"]+"' # Find forms without CSRF tokens grep -B5 -A20 '` + auto-submit script - Root cause: 2022-02-14 deploy inadvertently turned off CSRF middleware across all Stripe Dashboard endpoints - Year: 2022 — **$5,000** ($2,500 × 2 researchers) 14. **GitHub Enterprise Server — CSRF bypass via path traversal (CVE-2022-23732)** ([H1 #1497169](https://hackerone.com/reports/1497169)) - Subclass: CSRF token validation bypass (path traversal smuggles request past token check) - Payload: `` - Root cause: router matched the post-traversal path for execution but pre-traversal path for CSRF-protection scope, so the protected endpoint was reached without a valid token - Year: 2022 — **$10,000** 15. **HackerOne self — CSRF on social account linking → ATO** ([H1 #1727221](https://hackerone.com/reports/1727221)) - Subclass: account-link CSRF (social provider attach without state binding) - Payload: `