CSRF token flow
Follow a CSRF token from form to server check, then pick SameSite and server checks until four forged requests fail and your own three still work.
Goal
bank.example keeps you signed in with a session cookie. Any site you visit can make your browser send a request to the bank, and the browser decides whether your cookie goes with it.
Seven requests reach the bank: three are yours and four are forged by other pages. Pick the SameSite setting and the server checks until every forged request fails and yours still work.
Session cookie SameSite
Server
- 1
GET /transferThe server renders the form and puts a token tied to this session in a hidden field. - 2
<input type="hidden" name="csrf" value="lab-only-csrf-7f3a9c">Only pages from bank.example can read this value. The same-origin policy stops other sites from reading the response. - 3
POST /transfer csrf=lab-only-csrf-7f3a9cThe browser sends the session cookie automatically. The token is sent because the page put it in the form. - 4
Server compares the token with the one stored for the sessionA match proves the request came from a page the bank rendered, not just from a browser that has the cookie.
| Request | From | Cookie | Token | Result |
|---|---|---|---|---|
| YoursYou submit the transfer form on bank.example | POST /transferbank.example (same-origin) | sent | valid | performed The server performed the action. |
| YoursThe bank’s own page calls the API with the token in a header | POST /api/payeesbank.example (same-origin) | sent | valid | performed The server performed the action. |
| YoursYou click a link in the bank’s newsletter (sent from mail.example) to view your statements | GET /statementsmail.example (cross-site) | sent | none | page shown Read-only page shown with the session. |
| ForgedA page on prizes.example auto-submits a hidden form to /transfer | POST /transferprizes.example (cross-site) | sent | none | performed The server performed the action. |
| ForgedA forum post links to /transfer?to=lab-only-acct&amount=900 | GET /transferforum.example (cross-site) | sent | none | performed CSRF middleware skips safe methods, so this GET performed the transfer. |
| ForgedA compromised page on blog.bank.example submits a form to /transfer | POST /transferblog.bank.example (same-site) | sent | none | performed The server performed the action. |
| Forgedprizes.example submits the form with a guessed token | POST /transferprizes.example (cross-site) | sent | wrong value | performed The server performed the action. |
Steps
01Choose the cookie setting and server checks so that all four forged requests fail and all three of your own requests still work.
Do this in the workbench above. This step completes itself when the condition is met.
02With SameSite=Strict, which of your own requests stops working? Give the site it came from.
03Why does SameSite not stop the request from blog.bank.example?
04SameSite=Lax still sends the cookie on the forum link. What is the right fix?
05What makes the token work?