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)
- User logs into
bank.com→ session cookie stored - User visits
evil.com evil.comtriggers request tobank.com/transfer- Browser automatically attaches cookies
- Server cannot distinguish intent
Important: CSRF is not about reading responses — only about causing requests.
Glossary
| Term | Meaning |
|---|---|
| Ambient authority | Credentials automatically attached by the browser |
| State-changing request | Any request that mutates server state |
| CSRF token | Secret value tied to user/session and request context |
| SameSite cookie | Cookie attribute controlling cross-site inclusion |
| Origin header | Scheme + host + port of the initiating context |
| Referer header | URL of the page that initiated the request |
| Double submit cookie | Token strategy without server-side storage |
| Idempotent | Safe 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
| Placement | Pros | Cons |
|---|---|---|
| Hidden form field | Simple, standard | Not suitable for APIs |
| Custom header | Clean, JS-only | Requires JS |
| Cookie + header | Stateless | Easy to mis-implement |
Possible trap: Tokens in URLs are wrong (leak via logs, referrers).
Double Submit Cookie Pattern
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
| Mode | Cross-site behavior |
|---|---|
| Strict | Never sent |
| Lax | Sent on top-level GET navigations |
| None | Always sent (requires Secure) |
Modern default: SameSite=Lax
Practical Implications
SameSite=Laxblocks 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.
| Aspect | CSRF | CORS |
|---|---|---|
| Controls | Sending requests | Reading responses |
| Enforced by | Browser | Browser |
| Stops form POSTs | No | No |
| Stops JS fetch | No | Yes (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_emaillacks CSRF protection- Attacker forces request
- Password reset email sent to attacker
Example 2: OAuth Account Linking CSRF
- Missing or unchecked
stateparameter - 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=LaxorStrict- 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
stateis inherently CSRF-prone