This article describes a CSRF (Cross-Site Request Forgery) lab exercise where an attacker crafts a malicious webpage that silently submits a bank transfer form to a victim's logged-in session without their knowledge. The lab demonstrates how browsers automatically attach session cookies to requests, allowing attackers to perform unauthorized state-changing actions on behalf of authenticated users. Understanding CSRF is critical because it exploits a fundamental browser behavior to compromise account security, and the article shows both how the attack works and how to defend against it.
- Core CSRF mechanism and browser cookie behaviorCSRF succeeds because browsers automatically attach cookies to any request sent to the site that set them, regardless of which page initiated the request. An attacker creates a form on their controlled page with fields matching the target site's transfer endpoint, pre-fills it with malicious values (like attacker's account and $9,999), and makes it submit silently when the victim loads the page. The victim's browser includes their QuickBank session cookie with this cross-site request, causing QuickBank to accept it as a legitimate, authenticated action.
- Why the attacker needs no token or response accessCSRF works without the attacker reading the response because same-origin policy prevents cross-origin responses from being readable by JavaScript. For state-changing actions like transfers or email changes, simply sending the properly-formatted request is sufficient—the attacker doesn't need to see QuickBank's response to know the transfer succeeded. This contrasts with attacks like XSS that require reading sensitive data, making CSRF particularly effective against financial transactions.
- QuickBank's vulnerable implementationQuickBank uses only a session cookie to identify the user and contains no anti-CSRF token or origin validation on its transfer endpoint. This means every value in the transfer request (recipient, amount, user identity) is either guessable or already public, and there is nothing secret or unpredictable that an attacker must obtain. A form on any other site can exactly reproduce the bank's transfer request and succeed when the victim's browser automatically supplies the session cookie.
- Historical prevalence and modern defense shiftsCSRF was significant enough to hold its own entry in the OWASP Top 10 until 2017, but its prevalence declined due to two major changes: frameworks now include anti-CSRF tokens by default, and browser behavior evolved so that since 2020 Chrome treats cookies without a SameSite attribute as SameSite=Lax, which blocks most cross-site POST requests. However, CSRF still exists in custom code, legacy applications, cookie-based APIs, and anywhere protection has been explicitly disabled.
- Three-layer defense strategyThe article recommends three complementary defenses: use anti-CSRF tokens (synchroniser tokens) on every state-changing form and request, set the SameSite attribute on session cookies (at least Lax, Strict for sensitive operations), and check the Origin or Referer header as an additional validation layer. Additionally, state-changing operations should never use GET requests, and sensitive actions like transfers should require re-authentication or second-factor confirmation.
- High-value testing targets in real applicationsWhen testing with permission, attackers should prioritize state-changing requests lacking CSRF tokens, particularly email changes, password changes, and adding payees. Email-change CSRF is especially dangerous because it often leads directly to account takeover through the password reset mechanism, making it a high-impact vulnerability to identify and remediate in real applications.
- Why origin validation alone is insufficientQuickBank's vulnerability persists because it checks only the session cookie to identify the user but does nothing to verify that the request originated from QuickBank's own pages. Without a secret anti-CSRF token that only legitimate pages know, the bank cannot distinguish its own form from a forged one on an attacker's site, even if origin checks are theoretically present.
Bottom line: CSRF succeeds because browsers silently attach cookies to cross-site requests, allowing attackers to forge state-changing actions on behalf of authenticated users without reading responses. Every application handling sensitive operations must implement anti-CSRF tokens, enforce SameSite cookie attributes, validate request origins, and require re-authentication for critical actions to prevent this attack.
📋 In this walkthrough
What this lab teaches
Cross-site request forgery (CSRF) abuses the way browsers attach cookies automatically. If a site uses only a cookie to decide who you are, any other site can make your browser send a request to it, and that request will look like it came from you.
The attacker cannot read the response. They do not need to. For a state-changing action like a transfer, sending the request is enough.
How QuickBank handles transfers
QuickBank’s transfer form posts the recipient and amount and relies only on the session cookie to identify the user. There is no anti-CSRF token and no origin check. The lab shows the bank on one side and an attacker page on the other. It is solved when a transfer of $9,999 to attacker_account goes through from the victim’s session.
The attack approach
- Look at the bank’s transfer request: which fields it sends, and that nothing in it is secret or unpredictable.
- If every value can be guessed, a form on any other site can reproduce the request exactly.
- The victim’s browser will add the bank cookie by itself because the request is going to the bank’s address.
- Make the form submit automatically, so the victim only has to load the page.
Full walkthrough (spoiler)
Stuck after a few attempts? Open the steps below. Solving it yourself first is worth more XP, and more learning.
Show the step-by-step solution
- Click “Visit malicious page” to load the attacker site in the lab.
- Look at the hidden form it contains: it points at QuickBank’s transfer endpoint, with attacker_account and $9,999 already filled in.
- Click “Submit silently”. The form posts to QuickBank from the victim’s browser.
- The browser attaches the victim’s session cookie, QuickBank accepts the transfer as genuine, and the lab marks you solved.
Why it works
QuickBank checks who is sending the request, using the cookie, but not where it was started. Cookies are sent with every request to the site that set them, no matter which page triggered the request. Without a secret token that only the real site’s pages know, the bank cannot tell its own form from yours.
Where this happens in the real world
CSRF was common enough to hold its own place in the OWASP Top 10 until 2017. It fell out partly because frameworks now include CSRF tokens by default and partly because browsers changed: since 2020 Chrome treats cookies without a SameSite attribute as SameSite=Lax, which blocks most cross-site POSTs. It still appears in custom code, legacy apps, APIs that use cookies, and anywhere protection has been switched off.
How to defend against it
- Use anti-CSRF tokens (synchroniser tokens) on every state-changing form and request. Most frameworks do this for you.
- Set SameSite on session cookies, Lax at least, Strict for sensitive apps.
- Check the Origin or Referer header on state-changing requests as an extra layer.
- Never change state with GET requests.
- Ask again for sensitive actions, such as re-entering a password or confirming with a second factor for transfers.
Try it, then go further
Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.
