Skip to content

Cross-Site Request Forgery (CSRF)

Short definition: CSRF is about unintended authenticated state changes caused by ambient browser credentials.

Core Definition

CSRF occurs when a browser automatically includes credentials (cookies, HTTP auth, client certs) in a cross-origin request, allowing an attacker to trigger state-changing actions without user intent.

Required conditions:

  • Victim is authenticated
  • Attacker can cause the browser to send a request
  • Server relies on implicit authentication (cookies)

Mental Model (Browser Perspective)

  1. User logs into bank.com → session cookie stored
  2. User visits evil.com
  3. evil.com triggers request to bank.com/transfer
  4. Browser automatically attaches cookies
  5. Server cannot distinguish intent

Important: CSRF is not about reading responses — only about causing requests.

Glossary

TermMeaning
Ambient authorityCredentials automatically attached by the browser
State-changing requestAny request that mutates server state
CSRF tokenSecret value tied to user/session and request context
SameSite cookieCookie attribute controlling cross-site inclusion
Origin headerScheme + host + port of the initiating context
Referer headerURL of the page that initiated the request
Double submit cookieToken strategy without server-side storage
IdempotentSafe to repeat (GET should be idempotent)

Token Design

Properties of a Correct CSRF Token

A CSRF token must be:

  • Unpredictable (cryptographically random)
  • Bound to the user session
  • Verified server-side
  • Required on every state change

Common bindings:

  • Session ID
  • User ID
  • Per-request nonce (strongest)

Token Placement Tradeoffs

PlacementProsCons
Hidden form fieldSimple, standardNot suitable for APIs
Custom headerClean, JS-onlyRequires JS
Cookie + headerStatelessEasy to mis-implement

Possible trap: Tokens in URLs are wrong (leak via logs, referrers).

Mechanism:

  • Token stored in cookie
  • Same token sent in header or body
  • Server checks equality

Common failure modes:

  • Cookie not SameSite
  • Token not bound to session
  • XSS allows token theft

SameSite Cookies

SameSite Modes

ModeCross-site behavior
StrictNever sent
LaxSent on top-level GET navigations
NoneAlways sent (requires Secure)

Modern default: SameSite=Lax

Practical Implications

  • SameSite=Lax blocks most POST-based CSRF
  • Does not protect against:
    • Legacy browsers
    • Subdomain attacks
    • Same-site XSS
  • Should not be the only defense for high-risk actions

CORS vs CSRF

CORS does not prevent CSRF.

AspectCSRFCORS
ControlsSending requestsReading responses
Enforced byBrowserBrowser
Stops form POSTsNoNo
Stops JS fetchNoYes (read access only)

Key insight: A blocked CORS response still reaches the server.

Preflight Behavior

  • CSRF commonly uses:
    • <form>
    • <img>
    • <iframe>
  • These do not trigger CORS preflight
  • Preflight applies only to non-simple JS requests

Interview trap: “Preflight prevents CSRF” is false.

Browser Credential Rules

Browsers automatically attach:

  • Cookies (unless SameSite blocks)
  • HTTP Basic authentication
  • Client TLS certificates

Browsers do not attach:

  • Custom headers (unless JS)
  • Bearer tokens in Authorization (unless JS)

Result: Bearer-token APIs are CSRF-resistant by default.

Common Misconfigurations and Bypasses

Typical Failures

  • CSRF token only on HTML forms, not APIs
  • Token checked only on POST (PUT/DELETE ignored)
  • Token reusable across sessions
  • Missing validation on secondary endpoints

Real-World Bypass Patterns

  • State change via GET (/delete?id=123)
  • JSON endpoints without CSRF protection
  • Alternate content types (text/plain)
  • Weak origin validation (endswith("example.com"))
  • Missing checks on redirects or webhooks

Real-World Incident Patterns

Example 1: Email Change → Account Takeover

  • /change_email lacks CSRF protection
  • Attacker forces request
  • Password reset email sent to attacker

Example 2: OAuth Account Linking CSRF

  • Missing or unchecked state parameter
  • Victim account linked to attacker OAuth identity

Example 3: Admin Action CSRF

  • Admin panel protected by cookies and IP
  • CSRF triggers privileged action silently

Defense-in-Depth Checklist

Mandatory

  • CSRF token on every state-changing request
  • Server-side validation
  • No state changes via GET

Strongly Recommended

  • SameSite=Lax or Strict
  • Origin header validation
  • Explicit method handling

Situational

  • Per-request tokens
  • Step-up verification for sensitive actions

Key Takeaways

  • CSRF is about sending, not reading
  • SameSite is helpful but insufficient alone
  • CORS is orthogonal to CSRF
  • Token validation errors are more common than generation errors
  • OAuth without state is inherently CSRF-prone