Beginner·200 points·1 solve
Harborline — CSRF Account Takeover
Learn to recognise and close a CSRF (cross-site request forgery) gap on a state-changing endpoint. A browser attaches cookies to a request automatically, even when that request was triggered by a completely different website — so an endpoint that trusts "a valid session cookie arrived" as its only check can be driven by a page the victim never meant to interact with. You will not be asked to build an attacker page; the lab shows you one and runs it for you. Your job is to patch the handler and the cookie it issues.
handle_email_change() accepts csrf_token_submitted and origin_header as parameters but never checks either one — it changes the email for any request that carries a session cookie matching an existing session. issue_session_cookie() also sets no SameSite attribute, so that cookie is attached even to a cross-site request. Put the two together: a hidden, auto-submitting form on attacker.example, visited while the victim is signed in to Harborline in another tab, silently changes the victim's email — step one of an account takeover, since "forgot password" goes to that new address next. The standard, well-established fix is the synchronizer token pattern: issue a per-session random token the legitimate page embeds in its form, and reject any state-changing request that doesn't echo it back correctly — a cross-site attacker page has no way to read that token, because the browser's same-origin policy stops it reading Harborline's response. SameSite=Strict (or Lax) on the session cookie is a second, independent defence: it stops the browser attaching the cookie to a cross-site request at all. Either one closes this gap on its own; using both is standard defence-in-depth.
Your tasks
1
Open the lab and read the handler
handle_email_change() and issue_session_cookie() are shown in full on the lab page. Note which parameters are accepted but never checked.
2
See the risk, without crafting anything
Click "Run this demo" — it submits a forged request (valid session cookie, cross-site Origin, no CSRF token) for you and shows that it succeeds.
3
Add the token check
In the editor, reject the request (e.g. 403) when csrf_token_submitted does not match the session's stored csrf_token, before changing the email.
4
Add SameSite to the cookie
In issue_session_cookie(), add `; SameSite=Strict` (or `Lax`) to the returned cookie string — belt and suspenders.
5
Run the checker
The checker replays the forged request and confirms it is now rejected (by the token check and/or because the browser would never have attached a SameSite cookie cross-site), then confirms a request WITH the correct token still succeeds. Passing reveals the flag.
Submit the flag
Start the lab, capture the flag from the running machine, and submit it here.