Cross-Site Request Forgery (CSRF) is a web security vulnerability that tricks a user into unknowingly executing unauthorized actions on a trusted website. This attack exploits the trust a website has in a user’s browser and can lead to data theft, account takeovers, or fraudulent transactions.
Unlike Cross-Site Scripting (XSS), which targets users, CSRF targets authenticated users to perform unintended actions on a web application.
How CSRF Works
- User logs in to a legitimate website and remains authenticated (with active session cookies).
- Attacker tricks the user into clicking a malicious link, loading an image, or submitting a form.
- The request is automatically sent to the legitimate website using the user’s authentication session.
- The website processes the request as if the user had initiated it, without verifying the source.
📌 Example Scenario (CSRF in Bank Transactions):
- User logs into their online banking account (
bank.com
). - Attackers craft a malicious webpage with: htmlCopyEdit
<img src="https://bank.com/transfer?amount=5000&to=attacker_account" />
- If the victim visits this page while logged into
bank.com
, the request executes automatically, transferring $5000 to the attacker’s account.
Types of CSRF Attacks
1. Stored CSRF
- The malicious request is stored on the victim website and triggered later by users.
- This can be in comments, messages, or profiles.
2. Reflected CSRF
- The attacker sends a crafted link through emails, phishing messages, or social media.
- The request executes when the victim clicks the malicious link.
3. Login CSRF
- The attacker forces the victim to log into an attacker-controlled account.
- The victim unknowingly uses the attacker’s session, exposing sensitive data.
Consequences of CSRF Attacks
Unauthorized Transactions: Attackers can transfer money, change account details, or make purchases.
Account Hijacking: Attackers modify passwords or email addresses, locking out the victim.
Data Modification: Attackers change profile information, delete accounts, or post fake messages.
Malicious Actions: Attackers trigger requests to perform administrative actions on behalf of the victim.
CSRF Attack Example
Vulnerable Request (No CSRF Protection):
<form action="https://example.com/change-email" method="POST">
<input type="hidden" name="email" value="attacker@mail.com">
<input type="submit" value="Submit">
</form>
If a logged-in user clicks a hidden auto-submitting form, their email is changed to attacker@mail.com
.
Attack with an Auto-Submitting Script:
<body onload="document.forms[0].submit()">
<form action="https://example.com/transfer" method="POST">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="to" value="attacker_account">
</form>
</body>
The form submits automatically when the victim opens the webpage.
How to Prevent CSRF
1. CSRF Tokens (Synchronizer Token Pattern)
- Include unique, unpredictable tokens in every sensitive request.
- The server validates the token before processing the request.
Example (Adding a CSRF Token in HTML Forms):
<form action="/transfer" method="POST">
<input type="hidden" name="csrf_token" value="abcd1234xyz">
<input type="text" name="amount">
<input type="submit" value="Send Money">
</form>
Server-Side Validation (Python Flask Example):
if request.method == "POST":
if request.form["csrf_token"] != session["csrf_token"]:
abort(403) # Forbidden
The CSRF token is compared with the stored token before processing the request.
2. Use SameSite Attribute in Cookies
- Prevent browsers from sending cookies with cross-site requests.
Example (Setting Secure Cookies in HTTP Response Header):
Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Strict
This ensures cookies are not sent with cross-site requests.
3. Implement User Authentication Checks
- Require users to re-enter passwords or 2FA before performing sensitive actions.
Example (Requesting Password Confirmation):
<form action="/delete-account" method="POST">
Enter Password: <input type="password" name="password">
<input type="submit" value="Confirm">
</form>
This prevents automatic execution of sensitive actions.
4. Verify Referer and Origin Headers
- Check if requests come from trusted sources.
Example (Checking Headers in Python Flask):
if "Referer" not in request.headers or "mywebsite.com" not in request.headers["Referer"]:
abort(403) # Forbidden
If the request comes from an unknown domain, it is blocked.
5. Use Custom Request Headers
- Custom headers (e.g.,
X-Requested-With
) ensure requests originate from trusted sources.
Example (JavaScript Fetch API with Custom Headers):
fetch("/transfer", {
method: "POST",
headers: {
"X-Requested-With": "XMLHttpRequest"
},
body: JSON.stringify({ amount: 1000, to: "attacker_account" })
});
The server rejects requests without this header.
6. Implement CAPTCHAs
- Require users to manually verify actions.
- Prevent automated CSRF exploits.
Example (Google reCAPTCHA):
<form action="/transfer" method="POST">
<input type="text" name="amount">
<div class="g-recaptcha" data-sitekey="your-site-key"></div>
<input type="submit" value="Submit">
</form>
This blocks automated attacks while allowing legitimate users.
Testing for CSRF Vulnerabilities
Burp Suite – Detects and exploits CSRF weaknesses.
OWASP ZAP – Identifies CSRF flaws in web applications.
CSRF PoC Generator – Helps create proof-of-concept CSRF attacks.