Part II β The Shield Β· Lesson 3.15
Cross-Site Request Forgery (CSRF)
In one lineAnother site makes the user's browser send an authenticated request β cookies attach automatically.
Where you've seen itA hidden auto-submitting form on an unrelated page, POSTing to your bank while your session cookie is still valid.
Diagram
THE ATTACK β the browser is the confused deputy
1. user logs into bank.com cookie stored
2. user visits evil.com (same browser, same day)
3. evil.com contains:
<form action="https://bank.com/transfer" method="POST">
<input name="to" value="attacker">
<input name="amount" value="50000">
</form>
<script>document.forms[0].submit()</script>
4. browser sends the POST βββΊ bank.com
βββ cookie attached AUTOMATICALLY
5. server sees a valid session βββΊ transfer executes
The attacker never reads the response. They don't need to.WHY CORS DOESN'T SAVE YOU
CORS blocks READING a cross-origin response.
CSRF only needs the WRITE to happen.
form POST βββΊ sent, blocked from reading βββΊ damage already doneDEFENCES β layered, cheapest first
1. SameSite cookies Lax = not sent on cross-site POST β default
Strict = not sent on any cross-site nav
None = sent always (requires Secure)
2. CSRF token server issues per-session/per-form token,
attacker can't read it (same-origin policy)
ββββββββββ form + hidden token ββββββββββ
β Client β βββββββββββββββββββββΊ β Server β compare with session
ββββββββββ ββββββββββ
3. Origin / Referer check server rejects mismatched Origin header
4. Re-authenticate password or OTP for destructive actionsHow it works
- Cookies are attached by the browser based on destination, not on who initiated the request.
- So any site can cause an authenticated write unless something proves the request came from your UI.
SameSite=Lax(now the browser default) stops cross-sitePOSTs while keeping normal top-level navigation working.- CSRF tokens remain necessary where
SameSite=Noneis required (embedded flows, some SSO) β the double-submit cookie pattern is the common implementation. Authorization: Bearerheaders are not auto-attached, so token-in-header APIs are structurally CSRF-immune β but then you're exposed to XSS token theft instead (see 3.5).
Trade-offs
| Defence | Strength | Cost |
|---|---|---|
SameSite=Lax | Blocks most CSRF | Breaks legitimate cross-site POST flows |
SameSite=Strict | Strongest | User arrives from a link already "logged out" |
| CSRF token | Works with None | Server state or signed double-submit |
| Origin check | Simple, effective | Some proxies strip the header |
Interview angle
"Are you safe from CSRF if your API uses JWT in an Authorization header?"
- Structurally yes, because the browser never attaches that header automatically.
- But storing the JWT where JS can read it hands it to any XSS β you traded one risk for another.
- The balanced answer:
HttpOnly+Secure+SameSite=Laxcookies, plus a CSRF token on state-changing routes.
Recap
- CSRF abuses automatic cookie attachment; it needs the write, not the read.
SameSite=Laxcloses most of it; tokens cover the rest.- Header-based auth avoids CSRF but moves the risk to XSS β pick deliberately.