Problem Statement
Cross-Site Request Forgery (CSRF) is an attack that tricks a user's browser into making an unwanted request to a website where they are already authenticated. You encounter this problem because modern web applications rely on browsers automatically sending stored credentials (like session cookies) with every request, which attackers can exploit to perform actions on a user's behalf without their consent. Imagine this: a user is logged into their bank in one tab, then clicks a link in a phishing email—that simple click could secretly trigger a request to transfer funds because the browser automatically attaches their valid bank session.
Core Explanation
A CSRF attack works by exploiting the trust a web application has in a user's browser. Here’s the simple breakdown of how it happens:
- The Setup: A user logs into a legitimate site (e.g.,
yourapp.com). The site issues a session cookie, which their browser stores and automatically sends with every subsequent request toyourapp.com. - The Trap: The user, while still logged in, visits a malicious site (e.g., from a phishing email or a compromised ad). This site contains hidden, automatic code designed to trigger a request to
yourapp.com. - The Forgery: The user's browser, following the malicious site's instructions, makes a request to
yourapp.com. Crucially, it automatically includes the valid session cookie from the legitimate login. - The Result: The target application (
yourapp.com) receives a request that looks perfectly legitimate—it has the correct session cookie—so it executes the action, like changing an email address or making a transaction, thinking the user intended it.
Think of it like a forged signature stamp. Your browser holds the stamp (your session cookie). A CSRF attack is like a malicious actor secretly placing a document under your stamped hand—the application sees your valid stamp on the request and processes it, even though you never intended to sign that document.
Practical Context
You need to defend against CSRF whenever your web application performs state-changing actions (POST, PUT, PATCH, DELETE requests) that rely on authentication cookies or other browser-automatic credentials. This includes actions like updating a profile, changing a password, or processing a financial transaction.
You generally do not need CSRF protection for:
- Public, read-only operations (GET requests, though GET should never change state anyway).
- Stateless APIs that use tokens like JWTs in the
Authorizationheader (since browsers don’t automatically attach these headers to cross-site requests).
You should care because CSRF is a common and serious security flaw that can lead to compromised user accounts and data breaches. Modern frameworks (like Django, Rails, Spring Security, and Laravel) have built-in protections, but you must ensure they are properly enabled. If your app uses cookie-based sessions and has authenticated forms, CSRF defense is non-negotiable.
Quick Example
Consider a simple, vulnerable form in a banking app to transfer money:
<!-- Malicious site's code tricking a logged-in user -->
<body onload="document.forms[0].submit()">
<form action="https://yourbank.com/transfer" method="POST">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="toAccount" value="ATTACKER_ACCOUNT">
</form>
</body>
If the user is logged into yourbank.com, visiting this malicious page would automatically submit the form and complete the transfer, as the browser sends the user's valid session cookie.
A protected form includes a unique, secret CSRF token that the malicious site cannot guess or steal:
<!-- Your bank's legitimate form -->
<form action="https://yourbank.com/transfer" method="POST">
<input type="hidden" name="csrf_token" value="a9b3f7e2c1d5">
<input type="text" name="amount">
<input type="text" name="toAccount">
<button type="submit">Transfer</button>
</form>
The server validates this token with every state-changing request. The attacker's forged request lacks the valid token and is rejected.
Key Takeaway
The core defense is simple: for any state-changing request, verify that the user's browser intentionally sent the request, not just their credentials. The standard method is to use a unique, unpredictable CSRF token issued by your server. For a deep dive on implementation, consult the OWASP CSRF Prevention Cheat Sheet.
Top comments (0)