What Is a CSRF Attack?
Cross-Site Request Forgery (CSRF) is an attack that exploits the trust a web application has in an authenticated user's browser. Unlike Cross-Site Scripting (XSS), which injects malicious code into a page, CSRF doesn't need to steal credentials or inject anything — it simply tricks the browser into sending a legitimate-looking request that the user never intended to make.
The attack is possible because browsers automatically include cookies (including session cookies) with every request to a domain, regardless of where the request originates. An attacker on a malicious site can craft a request to your banking app, your email service, or your admin panel — and if the user is logged in, the browser will helpfully attach their session cookie.
How a CSRF Attack Works: Step by Step
- The victim logs into
https://bank.example.com. Their browser stores a session cookie. - Without logging out, the victim visits
https://attacker.example.com. - The attacker's page contains a hidden form or image tag targeting the bank:
<img src="https://bank.example.com/transfer?to=attacker&amount=5000"> - The browser fetches that URL, automatically attaching the victim's session cookie.
- The bank's server receives an authenticated request and processes the transfer.
The victim never clicked anything malicious. The browser behaved exactly as designed. The vulnerability lies in the server treating cookie presence as sufficient proof of intent.
High-Value CSRF Targets
Not all endpoints are equally risky. Attackers prioritize state-changing operations:
- Fund transfers and payment actions
- Email or password change endpoints
- Account deletion or privilege escalation
- Admin panel actions (user creation, config changes)
- API endpoints that modify data
Read-only GET endpoints are typically lower risk (though using GET for state changes is itself a problem).
CSRF Defense: A Layered Approach
1. SameSite Cookie Attribute (Primary Defense)
The SameSite attribute on cookies is now the most important CSRF defense. Setting it to Strict or Lax instructs browsers not to send the cookie on cross-site requests:
Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly
- Strict: Cookie is never sent on cross-site requests. Most secure, but may break legitimate cross-site navigation (e.g., clicking a link from an email).
- Lax: Cookie is sent on top-level navigations (GET requests via link clicks) but not on subresource requests or form POSTs. The default in modern browsers when no SameSite attribute is set.
- None: Cookie sent on all requests, including cross-site. Must be paired with
Secureand requires explicit opt-in. This is the legacy behavior — avoid unless required for cross-site functionality.
2. CSRF Tokens (Defense in Depth)
The classic mitigation: generate a random, unpredictable token per session (or per request for higher security), embed it in every state-changing form or AJAX request, and verify it server-side.
<input type="hidden" name="csrf_token" value="a8f3k2p9x...">
The server rejects any request where the token is missing or doesn't match the server-side value. An attacker on a different origin cannot read this token due to the Same-Origin Policy, so they cannot forge a valid request.
3. Double Submit Cookie Pattern
A stateless alternative to server-side token storage: set a random value as both a cookie and a request parameter. Verify they match. Since cross-site attackers can't read your cookies, they can't replicate the parameter value.
4. Verify the Origin Header
For AJAX requests, check the Origin or Referer header server-side. Requests originating from unexpected origins should be rejected. This is not foolproof (some browsers omit these headers) but is a useful additional check.
5. Require Re-Authentication for Sensitive Actions
For high-stakes operations — changing email, password, making transfers — require the user to re-enter their password. Even a successful CSRF cannot satisfy this requirement since the attacker doesn't know the user's credentials.
Defense Priority Summary
| Defense | Effectiveness | Implementation Effort |
|---|---|---|
| SameSite=Strict/Lax cookies | High (modern browsers) | Low — one attribute |
| CSRF tokens | High | Medium — requires server-side state |
| Origin/Referer validation | Medium (supplemental) | Low |
| Re-authentication | Very high (targeted actions) | High — UX consideration |
What Modern Frameworks Do For You
Most mature web frameworks (Django, Rails, Laravel, ASP.NET Core, Spring Security) include CSRF protection by default. Understand what your framework provides, ensure you haven't accidentally disabled it, and layer SameSite cookie attributes on top. Do not assume framework-provided protection eliminates all risk — misconfiguration is common.
CSRF is a well-understood, preventable vulnerability. With SameSite cookies now widely supported and CSRF tokens available in every major framework, there is no excuse for leaving state-changing endpoints unprotected.