L39 · Cross-Site Request Forgery (CSRF)

CS 161, Lesson 39, in 50 slides, on cross-site request forgery. It shows how an attacker rides the victim's automatically attached session cookie to forge state-changing requests, in section 21.1, covers CSRF based on GET and on POST, and explains why the same-origin policy does not stop it. It then gives the three defenses - CSRF tokens, Referer validation, and the SameSite cookie attribute - in sections 21.2 to 21.4. It is anchored to textbook sections 21.1 to 21.4.

Subject: Computer Security · 83 slides · applied lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. Cross-Site Request Forgery

Title

CS 161 · Lesson 39 of 45

How an attacker forges requests that ride your auto-attached session cookie — and why the same-origin policy doesn't stop it

2. By the end of this lesson you can…

Objectives

  1. Define CSRF: an attacker forces the victim's browser to make an unintended request to a site the victim is logged into, and the browser automatically attaches the session cookie.
  2. Construct GET-based CSRF (an auto-loading <img> or link) and POST-based CSRF (an auto-submitting form) against a toy target.
  3. Explain why the Same-Origin Policy doesn't stop CSRF — SOP blocks reading the response, but the request is still SENT with the cookie.
  4. Compare the three defenses — CSRF token, Referer validation, SameSite cookie — and say which is the primary defense and which are defense-in-depth.
  5. Distinguish CSRF from XSS and connect CSRF back to complete mediation and the L38 cookie model.

3. What survived from L38 · Cookies & Session Management?

Warm-up

Discussion prompt

Before we open L39 · Cross-Site Request Forgery (CSRF): without looking back, what was the main idea of L38 · Cookies & Session Management, and what could you do by the end of it that you could not do before?

Hint: One sentence for the idea, one for the skill. If the second one is blank, that is the part to revisit.

Answer:

CS 161, Lesson 38, in 53 slides. It explains why the statelessness of HTTP forces cookies, in section 20, then covers the cookie attributes in section 20.1, the send rule of domain-suffix plus path-prefix in section 20.2, and the set rule of suffix-of-server in section 20.3. It closes with session tokens and the gap between cookie policy and the same-origin policy that lets different origins share a cookie, in sections 20.4 and 20.5. It is anchored to textbook sections 20.1 to 20.5.

4. Why a whole lesson on CSRF

Concept

In L38 you saw that cookies keep you logged in: the browser attaches your session cookie to every request to a site. That convenience is exploitable — and CSRF is the attack that exploits it.

The attack
§21.1 forge a request that rides the cookie
Why SOP fails
§21.1 SOP guards reads, not sends
The defenses
§21.2–21.4 token · Referer · SameSite

5. Which is which: Why a whole lesson on CSRF

Matching

Match the pairs

From Why a whole lesson on CSRF — match each one to what it actually does. The descriptions have been shuffled.

  • c1. The attack
  • c2. Why SOP fails
  • c3. The defenses
  • b1. §21.1 forge a request that rides the cookie
  • b2. §21.1 SOP guards reads, not sends
  • b3. §21.2–21.4 token · Referer · SameSite

Why: The attack, Why SOP fails, The defenses are easy to tell apart while they are sitting next to their descriptions and much harder afterwards, which is what this checks.

6. The CSRF Attack

Section

Part 1 · §21.1 forging a request that rides the cookie

7. §21.1 What CSRF is

Concept

Concrete scenario: you're logged into bank.com in one tab. In another tab you open an attacker's page. That page silently makes your browser fire a request at bank.com — and bank.com treats it as if you meant it.

Cross-Site Request Forgery (CSRF) — An attack where the attacker forces the victim's browser to make an UNINTENDED request to a site the victim is logged into. The browser automatically attaches the session-token cookie, so the server accepts the request as if the victim made it intentionally.

8. §21.1 The key move: the cookie rides along

Concept

Here's the crux. The browser attaches your bank.com session cookie to any request sent to bank.com — it does not care WHICH page triggered the request. So a request triggered by the attacker's page still carries your cookie.

The attacker never sees or steals the cookie. They can't read it. They just trigger a request that the browser then decorates with your cookie automatically. The damage is done server-side, by a request the victim never intended.

9. §21.1 The signed blank check analogy

Intuition

Imagine you've pre-signed a stack of blank checks and left them with a trusted teller who fills in the details whenever a request 'from you' arrives. The signature is your session cookie; the teller is the browser.

The attacker can't COPY your signature — they never touch the checks. But they can mail the teller a note saying 'pay Mallory $100,' and the teller dutifully grabs a pre-signed check and processes it. Your signature was never stolen; it was just used.

Ask yourself: did the attacker need to know your signature? (No — they only needed to trigger a request the browser would sign for them.)

10. Break it if you can: §21.1 The signed blank check analogy

Counterexample

Discussion prompt

Ask yourself: did the attacker need to know your signature? (No — they only needed to trigger a request the browser would sign for them.)

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

11. What has to happen first: §21.1 Walk the CSRF flow end to end

Ranking

Put in order

Put the moves of §21.1 Walk the CSRF flow end to end into the order they have to happen.

  1. The victim logs into bank.com; the browser stores a session cookie for bank.com
  2. The victim, still logged in, visits the attacker's page evil.com
  3. evil.com's content makes the victim's browser send a request to bank.com
  4. Verify: did the attacker ever read the cookie? No — the browser attached it on its own

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. From L38: this cookie is how bank.com recognizes the victim on later requests.

12. §21.1 Walk the CSRF flow end to end

Worked example

The victim logs into bank.com; the browser stores a session cookie for bank.com

Why: From L38: this cookie is how bank.com recognizes the victim on later requests.

The victim, still logged in, visits the attacker's page evil.com

Why: The attacker's page contains HTML that will trigger a request to bank.com.

evil.com's content makes the victim's browser send a request to bank.com

Why: An <img>, a link, or an auto-submitting form — anything that issues an HTTP request to bank.com.

stepwho actswhat carries the cookie?
loginvictim → bank.comcookie set for bank.com
visit attackervictim → evil.comno bank.com cookie sent
forged requestbrowser → bank.comYES — cookie auto-attached
server actsbank.comaccepts it as the victim's intent

Verify: did the attacker ever read the cookie? No — the browser attached it on its own

Why: §21.1: the request goes to bank.com, so the browser attaches bank.com's cookie regardless of which page triggered it. The attacker only supplied the trigger.

13. Fill in: who acts for §21.1 Walk the CSRF flow end to end

Comparison

Comparison matrix

From §21.1 Walk the CSRF flow end to end: refill the who acts column from what you know. The rest of the table is as it appeared.

stepwho actswhat carries the cookie?
loginvictim → bank.comcookie set for bank.com
visit attackervictim → evil.comno bank.com cookie sent
forged requestbrowser → bank.comYES — cookie auto-attached
server actsbank.comaccepts it as the victim's intent

14. §21.1 'Cross-site' is the whole point

Concept

The 'cross-site' in CSRF names the trick exactly: the request originates from a different site (evil.com) than the one it targets and is authenticated against (bank.com). The victim's own browser is the bridge between the two.

From bank.com's side this is invisible — it just sees a well-formed, cookie-authenticated request. The cross-site origin of that request is precisely the fact bank.com cannot tell from the cookie alone, which is why a separate signal (a token, a Referer, a SameSite flag) is needed.

15. Something is wrong here: 'CSRF requires stealing the victim's cookie'

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student: 'For CSRF to work, the attacker has to somehow grab the victim's session token or read their cookie first.'

It is wrong. Say what breaks — and say it before you turn the page.

Correct: The attacker NEVER sees or steals the cookie — they can't read it across origins.

A student: what does the attacker actually need to do?

Why: The attacker NEVER sees or steals the cookie — they can't read it across origins. The browser attaches it automatically to any request bound for bank.com. The attacker only needs to TRIGGER the request.

16. Trap: 'CSRF requires stealing the victim's cookie'

Trap

The trap

A student: 'For CSRF to work, the attacker has to somehow grab the victim's session token or read their cookie first.'

Assume the attacker must obtain the cookie/session token

Why: Wrong. The attacker NEVER sees or steals the cookie — they can't read it across origins. The browser attaches it automatically to any request bound for bank.com. The attacker only needs to TRIGGER the request.

The fix

A student: what does the attacker actually need to do?

Just trigger a request to the target; the browser supplies the cookie

Why: §21.1: CSRF rides the auto-attached cookie. The attacker triggers a request to bank.com; the browser decorates it with the victim's cookie. No theft of the token is needed — that's what makes CSRF so easy.

17. GET-Based CSRF

Section

Part 2 · §21.1 links and auto-loading images

18. §21.1 If a state change is a GET, a link triggers it

Concept

Recall from L36: a GET should be side-effect-free, but the protocol doesn't enforce it. If a site wires a state-changing action to a GET endpoint, then merely loading that URL performs the action.

http://example.com/logout
  -> just loading this URL logs the victim out

https://bank.com/transfer?amount=100&recipient=mallory
  -> just loading this URL transfers $100 to mallory

19. By analogy: §21.1 If a state change is a GET, a link triggers it

Analogy

Discussion prompt

Explain §21.1 If a state change is a GET, a link triggers it by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Recall from L36: a GET should be side-effect-free, but the protocol doesn't enforce it. If a site wires a state-changing action to a GET endpoint, then merely loading that URL performs the action.

20. §21.1 The auto-loading <img> trick

Concept

The attacker doesn't even need the victim to click. An <img> tag tells the browser to fetch its src with a GET as soon as the page (or email) loads. Point the src at the state-changing URL.

<img src="https://bank.com/transfer?amount=100&recipient=mallory">

When the victim opens the email or page, the browser issues a GET to that URL, attaches the bank.com cookie, and the transfer goes through. The 'image' never renders — but the request already fired.

21. Teach it back: §21.1 The auto-loading <img> trick

Explain it

Discussion prompt

Explain §21.1 The auto-loading <img> trick to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

The attacker doesn't even need the victim to click. An <img> tag tells the browser to fetch its src with a GET as soon as the page (or email) loads. Point the src at the state-changing URL.

22. §21.1 The browser is eager, not thoughtful

Intuition

The browser sees <img src=...> and thinks 'I'd better go fetch that so I can show it.' It fires the GET FIRST and only afterward discovers the response isn't a valid image. By then the request — cookie and all — has already reached the server.

Ask yourself: does it matter that the response isn't really an image? (No — CSRF lives in the REQUEST. The transfer happened the instant the GET arrived; whether the response is a JPEG is irrelevant.)

23. Plan first: §21.1 Trace the <img> CSRF

Step zero

Discussion prompt

§21.1 Trace the <img> CSRF — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: Attacker emails the victim an HTML email containing an <img> tag

Answer:

  1. Attacker emails the victim an HTML email containing an <img> tag
  2. The victim (logged into bank.com) opens the email; the browser fetches the 'image'
  3. Verify: the broken-image icon is the only sign — and the money is already gone

24. §21.1 Trace the <img> CSRF

Worked example

Attacker emails the victim an HTML email containing an <img> tag

Why: The src points at bank.com/transfer?amount=100&recipient=mallory — a state-changing GET.

<!-- in the body of an email -->
<img src="https://bank.com/transfer?amount=100&recipient=mallory">

The victim (logged into bank.com) opens the email; the browser fetches the 'image'

Why: Loading an <img> issues a GET to its src automatically — no click required.

eventrequest sent?cookie attached?effect
email opensGET to bank.com/transferyes (bank.com cookie)server queues transfer
server checks auth—cookie = valid sessionlooks like the victim
server executes——$100 → mallory
browser 'renders'——broken image icon

Verify: the broken-image icon is the only sign — and the money is already gone

Why: §21.1: the GET fired and carried the cookie before the browser ever inspected the response. The damage is in the request, so a non-image response changes nothing.

25. Which is which, by request sent?

Discrimination

Sort into buckets

Sort these by request sent?, from memory, without looking back at §21.1 Trace the <img> CSRF. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.

GET to bank.com/transfer
email opens
—
server checks auth; server executes; browser 'renders'
g1
request sent? is "GET to bank.com/transfer" for email opens — that is what the table on "§21.1 Trace the <img> CSRF" records, and it is the single property separating this group from the rest.
g2
request sent? is "—" for server checks auth, server executes, browser 'renders' — that is what the table on "§21.1 Trace the <img> CSRF" records, and it is the single property separating this group from the rest.

26. §21.1 A bare link works too

Concept

An <img> fires automatically, but a plain hyperlink works the same way if the victim clicks it. Disguise the state-changing URL as something tempting and the click triggers the authenticated GET.

<a href="https://bank.com/transfer?amount=100&recipient=mallory">
  Click here to claim your free prize!
</a>

The <img> version is strictly stealthier — no click required — but both rely on the identical fact: loading or navigating to a bank.com URL sends a GET with the bank.com cookie attached.

27. §21.1 Note: state-changing GETs are bad practice

Concept

Because state-changing GET endpoints make CSRF this trivial, they're considered bad practice today — most sensitive actions are POST. So the pure <img>-CSRF form is less common now.

But moving to POST is not a fix — it just raises the bar slightly. As the next part shows, CSRF works fine over POST too.

28. Something is wrong here: 'an <img> tag can only load images'

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student: 'An <img> only loads images, so pointing its src at a transfer URL just produces a broken image — nothing happens.'

It is wrong. Say what breaks — and say it before you turn the page.

Correct: The browser issues the GET to the src REGARDLESS of what comes back.

A student: what does <img src=URL> actually do?

Why: The browser issues the GET to the src REGARDLESS of what comes back. It can't know it isn't an image until after the request is sent. The response just isn't a valid image — but the GET (with the cookie) already happened.

29. Trap: 'an <img> tag can only load images'

Trap

The trap

A student: 'An <img> only loads images, so pointing its src at a transfer URL just produces a broken image — nothing happens.'

Assume <img> won't fire a request unless the URL is a real image

Why: Wrong. The browser issues the GET to the src REGARDLESS of what comes back. It can't know it isn't an image until after the request is sent. The response just isn't a valid image — but the GET (with the cookie) already happened.

The fix

A student: what does <img src=URL> actually do?

It issues a GET to the URL with the site's cookie, then tries to draw the result

Why: §21.1: the request comes first, rendering second. So an <img> can trigger any GET endpoint, image or not. That's exactly what GET-based CSRF abuses.

30. POST-Based CSRF

Section

Part 3 · §21.1 auto-submitting forms

31. §21.1 CSRF survives the move to POST

Concept

Suppose bank.com/transfer now requires a POST. CSRF still works: the attacker's page builds a hidden HTML form aimed at bank.com and uses JavaScript to auto-submit it the moment the victim arrives.

Submitting a form sends an HTTP request — here a POST to bank.com — and, like any request to bank.com, the browser attaches the session cookie. The server executes the transfer as the victim.

32. §21.1 The auto-submitting form

Concept

The attacker page hides a form whose action is the bank's POST endpoint and whose inputs carry the attacker's chosen values. A one-line script submits it automatically.

<form name=evilform action=https://bank.com/transfer method=POST>
  <input name=amount value=100>
  <input name=recipient value=mallory>
</form>
<script>document.evilform.submit();</script>

No button, no click. document.evilform.submit() runs on page load, the browser POSTs to bank.com WITH the cookie, and bank.com transfers $100 to mallory.

33. §21.1 A form submit is just a request

Intuition

We tend to picture a form as something a human fills out and clicks 'Submit' on. But to the browser a form submit is just an HTTP request — and JavaScript can fire it without any human at all.

Ask yourself: from bank.com's point of view, does a POST from an auto-submitted evil.com form look any different from a POST from its own page? (No — same method, same fields, same cookie. That's the whole problem.)

34. Where does each piece belong: L39 · Cross-Site Request Forgery (CSRF)

Sorting

Sort into buckets

These are the pieces of L39 · Cross-Site Request Forgery (CSRF), out of order. Put each one back under the part of the lesson it belongs to.

The CSRF Attack
§21.1 What CSRF is; §21.1 The key move: the cookie rides along; §21.1 The signed blank check analogy
GET-Based CSRF
§21.1 If a state change is a GET, a link triggers it; §21.1 The auto-loading <img> trick; §21.1 The browser is eager, not thoughtful
POST-Based CSRF
§21.1 CSRF survives the move to POST; §21.1 The auto-submitting form; §21.1 A form submit is just a request
s1
The CSRF Attack is where L39 · Cross-Site Request Forgery (CSRF) puts §21.1 What CSRF is, §21.1 The key move: the cookie rides along, §21.1 The signed blank check analogy. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
GET-Based CSRF is where L39 · Cross-Site Request Forgery (CSRF) puts §21.1 If a state change is a GET, a link triggers it, §21.1 The auto-loading <img> trick, §21.1 The browser is eager, not thoughtful. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
POST-Based CSRF is where L39 · Cross-Site Request Forgery (CSRF) puts §21.1 CSRF survives the move to POST, §21.1 The auto-submitting form, §21.1 A form submit is just a request. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

35. Plan first: §21.1 Walk the auto-submit POST CSRF

Step zero

Discussion prompt

§21.1 Walk the auto-submit POST CSRF — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: The victim is logged into bank.com and visits the attacker's page

Answer:

  1. The victim is logged into bank.com and visits the attacker's page
  2. On load, document.evilform.submit() runs
  3. The browser sends a POST to https://bank.com/transfer with amount=100, recipient=mallory
  4. Verify: bank.com sees a valid session cookie + a transfer request, and executes it

36. §21.1 Walk the auto-submit POST CSRF

Worked example

The victim is logged into bank.com and visits the attacker's page

Why: The attacker page holds the hidden form + auto-submit script shown above.

On load, document.evilform.submit() runs

Why: The script fires immediately — the victim does nothing and clicks nothing.

The browser sends a POST to https://bank.com/transfer with amount=100, recipient=mallory

Why: Submitting the form issues the request; the browser attaches bank.com's session cookie because the request targets bank.com.

region of the POSTcontentwhere it came from
first linePOST /transfer HTTP/1.1the form's method + action
Hostbank.comthe action's domain
Cookiesession=<victim's>browser auto-attached it
bodyamount=100&recipient=mallorythe form's hidden inputs

Verify: bank.com sees a valid session cookie + a transfer request, and executes it

Why: §21.1: nothing distinguishes this forged POST from a real one. Switching the endpoint to POST did not stop the attack — it only required a form instead of an <img>.

37. What each one costs: §21.1 Walk the auto-submit POST CSRF

Trade off

Comparison matrix

From §21.1 Walk the auto-submit POST CSRF: every row here is a choice with a cost. Fill the where it came from column, then say which row you would actually pick and what you give up for it.

region of the POSTcontentwhere it came from
first linePOST /transfer HTTP/1.1the form's method + action
Hostbank.comthe action's domain
Cookiesession=<victim's>browser auto-attached it
bodyamount=100&recipient=mallorythe form's hidden inputs

38. §21.1 Why hidden inputs make it invisible

Concept

The attacker's form fields can be type=hidden, so nothing renders for the victim to notice. Combined with auto-submit, the whole forgery happens in the instant the attacker page loads — the victim may never even see it flash by.

The attacker also pre-fills every value (amount, recipient), so they fully control the forged action. The victim contributes only one thing: a valid logged-in session the browser silently attaches.

39. Something is wrong here: 'switching the endpoint to POST prevents CSRF'

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student: 'If I make the transfer endpoint require a POST instead of a GET, attackers can't forge it anymore.'

It is wrong. Say what breaks — and say it before you turn the page.

Correct: An attacker page can host a hidden form and auto-submit it with JavaScript, sending a POST to bank.com with the cookie attached.

A student: what does requiring POST actually buy you?

Why: An attacker page can host a hidden form and auto-submit it with JavaScript, sending a POST to bank.com with the cookie attached. POST raises the bar slightly over a bare <img>, but it does NOT stop CSRF.

40. Trap: 'switching the endpoint to POST prevents CSRF'

Trap

The trap

A student: 'If I make the transfer endpoint require a POST instead of a GET, attackers can't forge it anymore.'

Treat POST-only as a CSRF defense

Why: Wrong. An attacker page can host a hidden form and auto-submit it with JavaScript, sending a POST to bank.com with the cookie attached. POST raises the bar slightly over a bare <img>, but it does NOT stop CSRF.

The fix

A student: what does requiring POST actually buy you?

Almost nothing — auto-submitted forms send POSTs too

Why: §21.1: CSRF works over POST via auto-submitting forms. The real fix is an unguessable per-session token, not the choice of HTTP method.

41. Why the SOP Doesn't Stop CSRF

Section

Part 4 · §21.1 the key insight

42. §21.1 SOP guards reads, not sends

Concept

The Same-Origin Policy (L37) blocks the attacker's page from reading bank.com's RESPONSE. So why doesn't it stop CSRF? Because CSRF doesn't need the response at all.

The attacker's page is still allowed to SEND a request to bank.com — that's what <img>, links, and form submits do every day. SOP only stops the attacker from READING what comes back. The request goes out, cookie and all, before SOP has anything to say.

43. §21.1 The damage is in the request

Concept

CSRF's whole effect — the transfer, the logout, the state change — happens server-side, when the request arrives. The attacker doesn't care what bank.com replies; they already won the moment the request executed.

So a policy that guards the response (SOP) is the wrong tool against an attack whose payload is the request. SOP blocking the read is irrelevant when the harm is already done by the send.

44. §21.1 SOP locks the mailbox, not the slot

Intuition

Picture SOP as a lock on bank.com's incoming-mail box — it stops the attacker from reading the replies bank.com sends back. Fine. But the attacker isn't trying to read replies.

The attacker just drops a letter into the mail slot — a request that triggers an action. SOP never locked the slot; it only locked the reply box. CSRF posts a letter and walks away, never needing to read the answer.

Ask yourself: which direction does SOP protect? (The response coming back. CSRF attacks the request going out — the unguarded direction.)

45. What has to happen first: §21.1 Reason out why SOP can't catch the forged POST

Ranking

Put in order

Put the moves of §21.1 Reason out why SOP can't catch the forged POST into the order they have to happen.

  1. evil.com auto-submits a form POSTing to bank.com/transfer
  2. Ask what SOP actually governs at each step
  3. Verify: the only step SOP blocks is the one the attacker never needed

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. This is a cross-origin request: source origin evil.com, target origin bank.com.

46. §21.1 Reason out why SOP can't catch the forged POST

Worked example

evil.com auto-submits a form POSTing to bank.com/transfer

Why: This is a cross-origin request: source origin evil.com, target origin bank.com.

Ask what SOP actually governs at each step

Why: SOP restricts cross-origin READS of responses; it does not block the SENDING of the request itself.

stephappens?does SOP intervene?
browser sends POST to bank.comyesno — sending is allowed
browser attaches bank.com cookieyesno — cookie policy, not SOP
bank.com executes the transferyesno — it's server-side
evil.com's JS reads the responseblockedYES — but attacker doesn't care

Verify: the only step SOP blocks is the one the attacker never needed

Why: §21.1: the harm (the transfer) completes in the first three rows, all unguarded by SOP. SOP only kicks in at the read, which is irrelevant to a fire-and-forget attack. Hence a dedicated CSRF defense is required.

47. Fill in: does SOP intervene? for §21.1 Reason out why SOP can't catch the…

Comparison

Comparison matrix

From §21.1 Reason out why SOP can't catch the forged POST: refill the does SOP intervene? column from what you know. The rest of the table is as it appeared.

stephappens?does SOP intervene?
browser sends POST to bank.comyesno — sending is allowed
browser attaches bank.com cookieyesno — cookie policy, not SOP
bank.com executes the transferyesno — it's server-side
evil.com's JS reads the responseblockedYES — but attacker doesn't care

48. Something is wrong here: 'the same-origin policy blocks cross-site requests, so…

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student: 'The Same-Origin Policy stops evil.com from talking to bank.com, so a CSRF request would be blocked.'

It is wrong. Say what breaks — and say it before you turn the page.

Correct: SOP blocks the attacker from READING bank.com's response — it does NOT block the request from being SENT.

A student: what exactly does SOP restrict?

Why: SOP blocks the attacker from READING bank.com's response — it does NOT block the request from being SENT. Cross-site requests fire constantly (every <img>, link, and form). The cookie rides along and the server acts on it.

49. Trap: 'the same-origin policy blocks cross-site requests, so CSRF can't happen'

Trap

The trap

A student: 'The Same-Origin Policy stops evil.com from talking to bank.com, so a CSRF request would be blocked.'

Assume SOP blocks the cross-site REQUEST from being sent

Why: Wrong. SOP blocks the attacker from READING bank.com's response — it does NOT block the request from being SENT. Cross-site requests fire constantly (every <img>, link, and form). The cookie rides along and the server acts on it.

The fix

A student: what exactly does SOP restrict?

SOP restricts reading the response, not sending the request

Why: §21.1: the forged request is sent and executed with the cookie attached; SOP only stops the attacker from seeing the reply. Since CSRF's damage is the request itself, SOP doesn't help — that's why a separate defense (a CSRF token) is needed.

50. Defenses — Token, Referer, SameSite

Section

Part 5 · §21.2–21.4 in order of strength

51. §21.2 The CSRF token (primary defense)

Concept

The primary defense: the server embeds a random, unpredictable token as a (usually hidden) extra field in each legitimately-served form, and stores a mapping from CSRF token → session token. On submit, it checks that the token matches the session.

CSRF token — A random, unpredictable value the server places in each form it serves and maps to the user's session. A request is accepted only if it carries a token bound to that session — which a forged cross-site request can't supply.

52. Take the definitions apart: Cross-Site Request… vs CSRF token

Definition probe

Sort into buckets

Every line below is part of the definition of Cross-Site Request Forgery (CSRF) or of CSRF token — one or the other, never both. Put each where it belongs.

Cross-Site Request Forgery (CSRF)
An attack where the attacker forces the victim's browser to make an UNINTENDED request to a site the victim is logged into.; The browser automatically attaches the session-token cookie, so the server accepts the request as if the victim made it intentionally.
CSRF token
A random, unpredictable value the server places in each form it serves and maps to the user's session.; A request is accepted only if it carries a token bound to that session; which a forged cross-site request can't supply.
b1
An attack where the attacker forces the victim's browser to make an UNINTENDED request to a site the victim is logged into. The browser automatically attaches the session-token cookie, so the server accepts the request as if the victim made it intentionally.
b2
A random, unpredictable value the server places in each form it serves and maps to the user's session. A request is accepted only if it carries a token bound to that session — which a forged cross-site request can't supply.

53. §21.2 A form carrying a CSRF token

Concept

The legit form bank.com serves includes a hidden input holding the token. When the victim submits the real form, the token rides along and the server checks it against the session.

<!-- served by bank.com to a logged-in victim -->
<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="7Fx9...random...Qz2">
  <input name="amount">
  <input name="recipient">
</form>

The attacker's forged form has no valid csrf_token. They can't guess it (it's random) and can't read it out of the victim's real page (SOP blocks the cross-origin read). So the server rejects the forged request.

54. §21.2 Why the attacker can't get the token

Intuition

The token works because the attacker faces two walls at once. First, it's random, so they can't guess it. Second, the victim never legitimately loaded the form from the attacker's context, so there's no token bound to the victim's session for the attacker to copy.

And even if the token sits in the victim's real bank.com page, SOP stops the attacker's cross-origin JavaScript from reading it out of that page. The same SOP that fails to stop the request succeeds at hiding the token.

Note the cost: this needs server state — a token↔session mapping the server maintains and checks.

55. Plan first: §21.2 Why the forged request fails the token check

Step zero

Discussion prompt

§21.2 Why the forged request fails the token check — before any calculation: what is the plan? Name the moves in order, in plain English, without doing the arithmetic.

Hint: It starts with: bank.com serves the victim a form with a fresh hidden csrf_token…

Answer:

  1. bank.com serves the victim a form with a fresh hidden csrf_token bound to the victim's session
  2. evil.com auto-submits a forged POST to bank.com/transfer
  3. Verify: the cookie alone is no longer enough — the request also needs a session-bound token the attacker can't obtain

56. §21.2 Why the forged request fails the token check

Worked example

bank.com serves the victim a form with a fresh hidden csrf_token bound to the victim's session

Why: The server records the mapping csrf_token -> session in its state.

evil.com auto-submits a forged POST to bank.com/transfer

Why: The cookie still rides along automatically — but the forged form has no valid token.

requestcookie?valid csrf_token?server's decision
victim's real formyesyes (bound to session)ACCEPT
forged form (no token)yesno — missingREJECT
forged form (guessed token)yesno — won't matchREJECT
forged form (read token?)yescan't — SOP blocks readREJECT

Verify: the cookie alone is no longer enough — the request also needs a session-bound token the attacker can't obtain

Why: §21.2: the token separates 'a request that merely carries the cookie' from 'a request the user actually initiated on a real form.' That's why it's the primary defense.

57. Which is which, by server's decision

Discrimination

Sort into buckets

Sort these by server's decision, from memory, without looking back at §21.2 Why the forged request fails the token check. Telling them apart on the spot is the skill; the table is only where the answer happens to be written down.

ACCEPT
victim's real form
REJECT
forged form (no token); forged form (guessed token); forged form (read token?)
g1
server's decision is "ACCEPT" for victim's real form — that is what the table on "§21.2 Why the forged request fails the…" records, and it is the single property separating this group from the rest.
g2
server's decision is "REJECT" for forged form (no token), forged form (guessed token), forged form (read token?) — that is what the table on "§21.2 Why the forged request fails the…" records, and it is the single property separating this group from the rest.

58. §21.3 Referer validation (defense-in-depth)

Concept

The browser's Referer header tells the server which URL the request came from — bank.com for a legit form, evil.com for the attack. So the server can reject requests whose Referer it doesn't trust.

(Fun fact: Referer is a decades-old misspelling of 'referrer,' baked into the HTTP spec and now permanent.)

59. §21.3 Why Referer is only defense-in-depth

Concept

The problem: the Referer is often blank or stripped — for privacy reasons, by proxies, or by browser settings. So the server faces a dilemma with no good answer.

Neither choice is clean, so Referer validation is only defense-in-depth — a useful extra layer, never a standalone fix.

60. Teach it back: §21.3 Why Referer is only defense-in-depth

Explain it

Discussion prompt

Explain §21.3 Why Referer is only defense-in-depth to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

The problem: the Referer is often blank or stripped — for privacy reasons, by proxies, or by browser settings. So the server faces a dilemma with no good answer.

61. §21.4 The SameSite cookie attribute (defense-in-depth)

Concept

A cookie can be flagged SameSite: the browser then sends it only when the cookie's domain matches the request's origin domain. So a request from evil.com to bank.com simply won't carry bank.com's cookie — defusing CSRF at the source.

SameSite cookie attribute — A flag on a cookie telling the browser to send it only when the request's origin domain matches the cookie's domain. A cross-site request (evil.com → bank.com) then arrives without the cookie, so the server doesn't see a logged-in session.

Historically it wasn't implemented or behaved consistently across all browsers, so it's treated as defense-in-depth rather than a sole defense.

62. By analogy: §21.4 The SameSite cookie attribute (defense-in-depth)

Analogy

Discussion prompt

Explain §21.4 The SameSite cookie attribute (defense-in-depth) by analogy to something with no Computer Security in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Historically it wasn't implemented or behaved consistently across all browsers, so it's treated as defense-in-depth rather than a sole defense.

63. §21.4 SameSite: the cookie checks the return address

Intuition

The other two defenses let the cookie arrive and then scrutinize the request. SameSite is more direct: it tells the browser not to send the cookie in the first place when the request comes from a different site.

Think of the cookie as refusing to ride along unless the request's 'return address' (its origin site) matches the cookie's own home. A request stamped 'from evil.com' headed to bank.com simply travels without the bank.com cookie — so bank.com sees no logged-in session and won't act.

Ask yourself: why is this still only defense-in-depth? (Because historically not every browser implemented it the same way — you can't rely on it being enforced everywhere, so you don't drop the token.)

64. §21.2–21.4 The defenses at a glance

Concept

Three defenses, in order of strength. Read each as 'how it works' and, crucially, 'what its limitation is.'

defensehow it workslimitation
CSRF token (§21.2)random session-bound token in each form; checked on submit; attacker can't read or guess it (SOP blocks the read)needs server state (token↔session mapping)
Referer validation (§21.3)reject requests whose Referer isn't the site itselfReferer often blank/stripped → must break users or accept a hole
SameSite cookie (§21.4)browser won't send the cookie on cross-site requests at allhistorically inconsistent browser support

65. Break it if you can: §21.2–21.4 The defenses at a glance

Counterexample

Discussion prompt

Three defenses, in order of strength. Read each as 'how it works' and, crucially, 'what its limitation is.'

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

66. What has to happen first: §21.2–21.4 Run one forged request past all three…

Ranking

Put in order

Put the moves of §21.2–21.4 Run one forged request past all three defenses into the order they have to happen.

  1. evil.com auto-submits a POST to bank.com/transfer; the browser attaches the cookie
  2. Note which defense fails open and why
  3. Verify: only the CSRF token rejects the request without depending on the browser or the Referer being well-behaved

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. Same forged request as before — now we see what each defense does to it.

67. §21.2–21.4 Run one forged request past all three defenses

Worked example

evil.com auto-submits a POST to bank.com/transfer; the browser attaches the cookie

Why: Same forged request as before — now we see what each defense does to it.

defense in placewhat the forged request lacksoutcome
CSRF tokenno valid session-bound token (can't read/guess it)REJECTED — reliably
Referer validationReferer says evil.com (or is blank)rejected if Referer present; HOLE if blank
SameSite cookiecookie not sent on the cross-site requestrejected where SameSite is enforced

Note which defense fails open and why

Why: Referer validation fails open on blank Referers, and SameSite fails where a browser doesn't enforce it — so both are defense-in-depth around the token.

Verify: only the CSRF token rejects the request without depending on the browser or the Referer being well-behaved

Why: §21.2–21.4: the token is self-contained server-side state the attacker can't satisfy, which is why it's the primary defense and the other two are layered on top.

68. What each one costs: §21.2–21.4 Run one forged request past all three…

Trade off

Comparison matrix

From §21.2–21.4 Run one forged request past all three defenses: every row here is a choice with a cost. Fill the outcome column, then say which row you would actually pick and what you give up for it.

defense in placewhat the forged request lacksoutcome
CSRF tokenno valid session-bound token (can't read/guess it)REJECTED — reliably
Referer validationReferer says evil.com (or is blank)rejected if Referer present; HOLE if blank
SameSite cookiecookie not sent on the cross-site requestrejected where SameSite is enforced

69. §21.1 CSRF vs XSS — a sharp line

Concept

Students conflate CSRF and XSS, but they differ on one axis: does the attacker get to run code inside the target origin? CSRF does NOT — it only triggers a request from the outside and never reads the response.

CSRF (L39)XSS (L40)
attacker code runs in target origin?noYES
reads the response?no — fire and forgetyes — full DOM access
rides the auto-attached cookie?yesyes (and can read it)
severityforge specific requestsfar worse — owns the page

CSRF rides the cookie from outside; XSS breaks INTO the origin and runs script there. That's why XSS (next lesson) is strictly more powerful.

70. Fill in: XSS (L40) for §21.1 CSRF vs XSS — a sharp line

Comparison

Comparison matrix

From §21.1 CSRF vs XSS — a sharp line: refill the XSS (L40) column from what you know. The rest of the table is as it appeared.

CSRF (L39)XSS (L40)
attacker code runs in target origin?noYES
reads the response?no — fire and forgetyes — full DOM access
rides the auto-attached cookie?yesyes (and can read it)
severityforge specific requestsfar worse — owns the page

71. Something is wrong here: 'Referer validation alone fully stops CSRF'

Anomaly

Predict first

A student writes this, and it looks reasonable:

A student: 'I'll just check the Referer header and reject anything not from bank.com — that completely stops CSRF.'

It is wrong. Say what breaks — and say it before you turn the page.

Correct: The Referer is often blank or stripped (privacy, proxies, browser settings).

A student: where does Referer validation fit?

Why: The Referer is often blank or stripped (privacy, proxies, browser settings). If you reject blank Referers you break real users; if you accept them you leave a CSRF hole. Either way it can't stand alone.

72. Trap: 'Referer validation alone fully stops CSRF'

Trap

The trap

A student: 'I'll just check the Referer header and reject anything not from bank.com — that completely stops CSRF.'

Rely on Referer validation as the sole defense

Why: Wrong. The Referer is often blank or stripped (privacy, proxies, browser settings). If you reject blank Referers you break real users; if you accept them you leave a CSRF hole. Either way it can't stand alone.

The fix

A student: where does Referer validation fit?

Use it as defense-in-depth behind a CSRF token

Why: §21.3: Referer validation is a useful extra layer but unreliable because of stripped headers. The primary defense is the CSRF token; Referer and SameSite are defense-in-depth on top of it.

73. Which of these survive contact with L39 · Cross-Site Request Forgery (CSRF)?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
Ask yourself: did the attacker need to know your signature? (No — they only needed to trigger a request the browser would sign for them.); The attacker page hides a form whose action is the bank's POST endpoint and whose inputs carry the attacker's chosen values. A one-line script submits it automatically.; The Same-Origin Policy (L37) blocks the attacker's page from reading bank.com's RESPONSE. So why doesn't it stop CSRF? Because CSRF doesn't need the response at all.
Breaks
A student: 'For CSRF to work, the attacker has to somehow grab the victim's session token or read their cookie first.'; A student: 'An <img> only loads images, so pointing its src at a transfer URL just produces a broken image — nothing happens.'
sound
These are stated as this lesson states them — each one survives the edge cases L39 · Cross-Site Request Forgery (CSRF) puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

74. Without one step: The CSRF playbook

Constraint

Discussion prompt

Run The CSRF playbook with this step confiscated:

Why SOP doesn't save you: SOP blocks READING the response, not SENDING the request; the damage is server-side in the request, so SOP is irrelevant.

Is it still possible? If it is, say what takes its place and what it costs you. If it is not, say exactly what that step was providing that nothing else does.

Hint: A step you can drop for free was never load-bearing. If you cannot drop it, name the thing that goes wrong the moment it is gone.

Answer:

  1. Spot the setup: the victim is logged into a target site, so the browser holds a session cookie it will auto-attach to ANY request to that site.
  2. Forge the request: trigger a request to the target from attacker-controlled content — a GET via <img src>/link (if state-changing GETs exist), or a POST…
  3. The cookie rides free: the browser attaches the session cookie because the request targets the site — the attacker never reads or steals it.
  4. Why SOP doesn't save you: SOP blocks READING the response, not SENDING the request; the damage is server-side in the request, so SOP is irrelevant.
  5. Defend, in order of strength: CSRF token (random, session-bound, unreadable cross-origin — the primary defense, needs server state) → Referer validation…
  6. Remember the contrast: CSRF rides the cookie WITHOUT reading the response; XSS (L40) breaks INTO the origin and runs script there — far worse.

75. The CSRF playbook

Pattern

  1. Spot the setup: the victim is logged into a target site, so the browser holds a session cookie it will auto-attach to ANY request to that site.
  2. Forge the request: trigger a request to the target from attacker-controlled content — a GET via <img src>/link (if state-changing GETs exist), or a POST via a hidden auto-submitting <form> + document.form.submit().
  3. The cookie rides free: the browser attaches the session cookie because the request targets the site — the attacker never reads or steals it.
  4. Why SOP doesn't save you: SOP blocks READING the response, not SENDING the request; the damage is server-side in the request, so SOP is irrelevant.
  5. Defend, in order of strength: CSRF token (random, session-bound, unreadable cross-origin — the primary defense, needs server state) → Referer validation (defense-in-depth; Referer often blank) → SameSite cookie (defense-in-depth; historically inconsistent).
  6. Remember the contrast: CSRF rides the cookie WITHOUT reading the response; XSS (L40) breaks INTO the origin and runs script there — far worse.

76. Where does it stop working: The CSRF playbook

Edge cases

Discussion prompt

The CSRF playbook works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".

Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.

Answer:

  1. Spot the setup: the victim is logged into a target site, so the browser holds a session cookie it will auto-attach to ANY request to that site.
  2. Forge the request: trigger a request to the target from attacker-controlled content — a GET via <img src>/link (if state-changing GETs exist), or a POST…
  3. The cookie rides free: the browser attaches the session cookie because the request targets the site — the attacker never reads or steals it.
  4. Why SOP doesn't save you: SOP blocks READING the response, not SENDING the request; the damage is server-side in the request, so SOP is irrelevant.
  5. Defend, in order of strength: CSRF token (random, session-bound, unreadable cross-origin — the primary defense, needs server state) → Referer validation…
  6. Remember the contrast: CSRF rides the cookie WITHOUT reading the response; XSS (L40) breaks INTO the origin and runs script there — far worse.

77. Rule out three: Checkpoint — which statement is TRUE?

Elimination

Eliminate the wrong options

Which statement about this CSRF attack is TRUE?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. The attack only works if evil.com first steals the victim's bank.com session cookie.
  • B. Requiring the transfer endpoint to use POST instead of GET would have prevented the attack.
  • C. The Same-Origin Policy blocks evil.com from sending the request to bank.com, so the attack fails.
  • D. The browser auto-attaches the bank.com cookie to the forged POST, so a server-checked CSRF token — which the forged form can't supply — is what actually stops it.

Survives elimination: D

Why: §21.1–21.2: because the forged POST targets bank.com, the browser automatically attaches the victim's session cookie, and the server would treat it as the victim's intent. The real defense is a CSRF token: a random, session-bound value the server places in each legitimate form and verifies on submit. The attacker can neither guess it nor read it out of the victim's real page (SOP blocks the cross-origin read), so the forged request is rejected. The other options each rest on a common misconception about CSRF.

78. Checkpoint — which statement is TRUE?

Check

A victim is logged into bank.com and visits evil.com, which auto-submits a hidden form POSTing to bank.com/transfer. Think through cookie attachment, the role of the SOP, and how a CSRF token would change the outcome before choosing.

Check your understanding

Which statement about this CSRF attack is TRUE?

  • A. The attack only works if evil.com first steals the victim's bank.com session cookie.
  • B. Requiring the transfer endpoint to use POST instead of GET would have prevented the attack.
  • C. The Same-Origin Policy blocks evil.com from sending the request to bank.com, so the attack fails.
  • D. The browser auto-attaches the bank.com cookie to the forged POST, so a server-checked CSRF token — which the forged form can't supply — is what actually stops it. (correct)

Answer: D

Why: §21.1–21.2: because the forged POST targets bank.com, the browser automatically attaches the victim's session cookie, and the server would treat it as the victim's intent. The real defense is a CSRF token: a random, session-bound value the server places in each legitimate form and verifies on submit. The attacker can neither guess it nor read it out of the victim's real page (SOP blocks the cross-origin read), so the forged request is rejected. The other options each rest on a common misconception about CSRF.

Why A tempts people
The attacker never sees or steals the cookie — they can't read it across origins. The browser attaches it automatically to any request bound for bank.com; the attacker only has to TRIGGER the request.
Why B tempts people
Switching to POST does not stop CSRF: an attacker page can host a hidden form and auto-submit it with JavaScript, sending a POST to bank.com with the cookie attached. POST is barely more work than an <img>.
Why C tempts people
The SOP blocks evil.com from READING bank.com's response, not from SENDING the request. The forged request is sent and executed with the cookie; SOP guards reads, not sends, so it doesn't stop CSRF.

79. Misconceptions to retire

Concept

80. Synthesis — CSRF is the dark side of the cookie model

Concept

81. Primary sources & where to read more

Concept

82. Connect it up: L39 · Cross-Site Request Forgery (CSRF)

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — The CSRF Attack · GET-Based CSRF · POST-Based CSRF · Why the SOP Doesn't Stop CSRF · Defenses — Token, Referer, SameSite. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

83. Recap — Lesson 39

Recap

You can now define CSRF as a forged, unintended request riding the browser's auto-attached session cookie; build it over GET (an <img>) and POST (an auto-submitting form); explain why the Same-Origin Policy doesn't stop it (SOP guards reads, not sends); and rank the three defenses — CSRF token (primary), Referer validation and SameSite (defense-in-depth) — while distinguishing CSRF from XSS.

Idea§The one-line version
The attack21.1forced unintended request; browser auto-attaches the cookie
No theft21.1attacker never reads the cookie — only triggers the request
GET CSRF21.1<img src=transfer-url> fires a GET with the cookie
POST CSRF21.1hidden auto-submitting form POSTs with the cookie
Why SOP fails21.1SOP blocks reading the RESPONSE, not sending the request
CSRF token21.2random session-bound token; primary defense; needs server state
Referer / SameSite21.3–21.4defense-in-depth: blank Referers; inconsistent SameSite
vs XSS—CSRF rides the cookie; XSS (L40) runs script in the origin

Sources

  1. CS 161 Computer Security Textbook §21.1–21.4 — Wagner, Weaver, Kao, Shakir, Law & Ngai, UC Berkeley — the CSRF attack and the browser's automatic cookie attachment (§21.1), GET-based and POST-based CSRF, and the three defenses: CSRF tokens (§21.2), Referer validation (§21.3), and the SameSite cookie attribute (§21.4)
  2. OWASP Cross-Site Request Forgery Prevention Cheat Sheet — OWASP Foundation — the primary practitioner reference for CSRF defenses: synchronizer (anti-CSRF) tokens, the SameSite cookie attribute, and verifying origin/Referer headers as defense-in-depth
  3. Robust Defenses for Cross-Site Request Forgery — A. Barth, C. Jackson & J. C. Mitchell, ACM CCS 2008 — the foundational academic treatment of CSRF and the case for token-based and Referer/Origin-header defenses
  4. RFC 6265bis — Cookies: HTTP State Management Mechanism (SameSite) — S. Bingler, M. West & J. Wilander (eds.), IETF — defines the SameSite cookie attribute (Strict/Lax/None) that controls whether a cookie is sent on cross-site requests

Want this taught 1-on-1? Alexander tutors Computer Security — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108