EN/CH Mode
BRUCE_FE Interview Notes - CSRF Cookie Cross-Site Attack
In-depth analysis of CSRF attack principles, hazards, and defense mechanisms. Learn how to use SameSite Cookie, CSRF Token, and other methods to protect web applications from cross-site request forgery attacks.
EN/CH Mode
Lazy to read articles? Then watch videos!
What is CSRF Attack?
Cross-Site Request Forgery (CSRF) is an attack that tricks you into performing unintended actions without your knowledge. Imagine someone forging your signature to withdraw money from the bank.
🔍 How CSRF Attack Works
Browser receives authentication cookie
Contains code that automatically sends requests (with cookies)
Bank website mistakenly thinks it's your operation
Simple CSRF attack example:
<!-- CSRF attack using GET method -->
<img src="https://bank.com/transfer?to=hacker&amount=1000" style="display:none">
<!-- When you visit a page containing this code, a transfer request is automatically sent -->
<!-- CSRF attack using POST method -->
<form id="csrf-form" action="https://bank.com/api/transfer" method="POST" style="display:none">
<input type="hidden" name="to" value="hacker">
<input type="hidden" name="amount" value="1000">
</form>
<script>
// Automatically submit the form after page load
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('csrf-form').submit();
});
</script>
How CSRF Attack Works
Three key conditions for a successful CSRF attack:
- 1. The user is authenticated on the target site and has an authentication cookie.
- 2. Cookies are sent automatically with requests, even from different sites.
- 3. The attacker tricks the victim into visiting a malicious page or clicking a malicious link.
Attack Flow Example
Scenario Setup:
- 1. User is logged in to the bank website (bank.com), browser stores authentication cookie.
- 2. The bank website has a transfer API:
POST /api/transfer
- 3. The attacker owns a malicious website (evil.com)
Step 1: User logs in to the bank website
// Cookie received after user logs in to the bank website
Set-Cookie: session=abc123; Domain=bank.com; Path=/; HttpOnly; Secure
Step 2: Attacker prepares malicious website
<!-- HTML code on malicious site (evil.com) -->
<html>
<body>
<h1>Win a free prize!</h1>
<!-- Hidden form auto-submitted -->
<form id="csrf-form" action="https://bank.com/api/transfer" method="POST" style="display:none;">
<input type="hidden" name="to" value="attacker-account" />
<input type="hidden" name="amount" value="1000" />
</form>
<script>
// Automatically submit the form after page load
window.onload = function() {
document.getElementById("csrf-form").submit();
}
</script>
</body>
</html>
Step 3: Victim visits malicious website
When the user visits evil.com, the malicious script automatically submits the form to bank.com, and the browser automatically attaches the user's bank cookie.
POST /api/transfer HTTP/1.1
Host: bank.com
Cookie: session=abc123
Content-Type: application/x-www-form-urlencoded
to=attacker-account&amount=1000
Step 4: Bank website processes the request
The bank website sees a valid session cookie, assumes the request is from a legitimate user, and processes the transfer.
Common Forms of CSRF Attacks
1. GET Request Attack
Use image tags or other resource requests to perform attacks:
<!-- Malicious image tag triggers GET request -->
<img src="https://bank.com/api/transfer?to=attacker&amount=1000" width="0" height="0" />
2. POST Request Attack
As in the previous example, use an auto-submitted form:
<form id="csrf-form" action="https://bank.com/api/transfer" method="POST">
<input type="hidden" name="to" value="attacker-account" />
<input type="hidden" name="amount" value="1000" />
</form>
<script>document.getElementById("csrf-form").submit();</script>
3. AJAX Request Attack
Use JavaScript to initiate XMLHttpRequest or fetch requests:
// Note: This method is usually restricted by same-origin policy and CORS
fetch('https://bank.com/api/transfer', {
method: 'POST',
credentials: 'include', // Key: include cookies
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: 'to=attacker-account&amount=1000'
})
.then(response => console.log('CSRF attack succeeded'))
.catch(error => console.error('CSRF attack failed', error));
4. Clickjacking (UI Redressing)
Combining transparent iframes and social engineering to trick users into clicking malicious buttons:
<style>
.game { position: relative; width: 500px; height: 500px; }
.overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 10; }
iframe { position: absolute; top: 0; left: 0; width: 500px; height: 500px; opacity: 0.0001; }
</style>
<div class="game">
<button class="overlay">Click to claim prize</button>
<!-- Semi-transparent iframe positioned above the bank site's 'Confirm Transfer' button -->
<iframe src="https://bank.com/transfer?to=attacker&amount=1000"></iframe>
</div>
CSRF Attack Defense Strategies
❌ Common Misconceptions
'CORS restricts cross-site requests, so CSRF is not possible'
Wrong! Browsers allow cross-site form submissions or image requests (e.g., <img src="...">), which are not restricted by CORS.
There are several ways to protect your site from CSRF attacks. Here are the most effective strategies:
1. SameSite Cookie Attribute
This is currently the most recommended defense. By setting the SameSite attribute on cookies, you can restrict cookies from being sent with cross-site requests:
Set-Cookie: session=abc123; SameSite=Strict; Path=/; HttpOnly; Secure
SameSite options:
- 1. Strict: Cookies are only sent for requests from the same site (most secure, but worse user experience)
- 2. Lax: Cookies are sent for top-level navigation and GET requests to the target site, but not for other cross-site requests (balance of security and UX, default in modern browsers)
- 3. None: Allows cookies to be sent cross-site, but must also set Secure attribute (not secure, use only when necessary)
2. CSRF Token
Use randomly generated tokens to verify the legitimacy of requests:
Server generates and stores CSRF Token:
// Node.js Express example
const crypto = require('crypto');
app.get('/form', (req, res) => {
// Generate random token
const csrfToken = crypto.randomBytes(16).toString('hex');
// Store in user session
req.session.csrfToken = csrfToken;
// Embed token in form
res.send(
'<form action="/api/transfer" method="POST">' +
'<input type="hidden" name="_csrf" value="' + csrfToken + '" />' +
'<!-- other form fields -->' +
'<button type="submit">Confirm Transfer</button>' +
'</form>'
);
});
Server validates the token:
// Middleware to validate CSRF Token
app.post('/api/transfer', (req, res) => {
// Get token from request
const csrfToken = req.body._csrf;
// Validate token
if (csrfToken !== req.session.csrfToken) {
return res.status(403).json({ error: 'CSRF token validation failed' });
}
// Token valid, process request
// ...
});
CSRF Token is effective because malicious sites cannot obtain the cross-origin token value, so they cannot construct requests with the correct token.
3. Double Submit Cookie
No server storage required, store the token in both the cookie and the request parameter:
// Set a cookie only for CSRF protection
app.get('/form', (req, res) => {
const csrfToken = crypto.randomBytes(16).toString('hex');
// Set cookie (add SameSite=Lax for better security)
res.cookie('csrf', csrfToken, {
httpOnly: false,
sameSite: 'Lax',
secure: true
});
// Also include the same token in the form
res.send(
'<form action="/api/transfer" method="POST">' +
'<input type="hidden" name="_csrf" value="' + csrfToken + '" />' +
'<!-- other form fields -->' +
'</form>'
);
});
// On validation, compare the token in the cookie and the one submitted in the form
app.post('/api/transfer', (req, res) => {
if (req.cookies.csrf !== req.body._csrf) {
return res.status(403).json({ error: 'Validation failed' });
}
// Process request...
});
Common CSRF Interview Questions
1. What is the difference between CSRF and XSS attacks?
A: The attack methods and purposes are different:
CSRF
Uses logged-in state to send forged requests
Cannot read data, can only perform actions
Defense: Validate request origin
XSS
Injects and executes malicious scripts
Can read data and execute arbitrary JS
Defense: Filter input, encode output
2. Why is SameSite Cookie an effective defense against CSRF?
A: SameSite restricts cookies to be sent only in specific situations:
Strict
Only same-site requests send cookies
Set-Cookie: session=123; SameSite=Strict;
Lax (Modern Browser Default)
Allows top-level navigation and GET requests to send cookies
Set-Cookie: session=123; SameSite=Lax;
CSRF attacks require cookies to be sent automatically, SameSite directly blocks this mechanism.
3. How does CSRF Token work?
A: Use randomly generated tokens to verify the legitimacy of requests:
Server generates random token
Put in form or JS request
Check if token matches
// Frontend form
<form>
<input type="hidden" name="_csrf" value="random token">
<!-- Other form fields -->
</form>
// Backend validation
if (req.body._csrf !== session.csrfToken) {
return res.status(403).send("Request denied");
}
Due to same-origin policy, malicious sites cannot read the target site's token, so they cannot construct valid requests.
4. Do I still need CSRF Token when setting SameSite Cookie?
A: Usually not both defenses are needed at the same time, but in some cases, both might be needed:
SameSite=Lax (recommended setting) is usually sufficient:
- 1. Prevents most CSRF attacks
- 2. Allows normal navigation from external site links
- 3. Default behavior in modern browsers
When to use CSRF Token together:
- 1. Need to support older browsers (don't support SameSite attribute)
- 2. Must use SameSite=None (e.g., third-party integration scenarios)
- 3. Need higher security level applications (e.g., financial services)
- 4. Practice of Defense in Depth strategy
// Best practice: Combine both
// 1. Set SameSite Cookie
app.use(session({
cookie: {
secure: true,
httpOnly: true,
sameSite: 'lax' // Default value, blocks most CSRF
}
}));
// 2. Critical operations still use CSRF Token as additional protection
app.post('/api/payment', csrfProtection, (req, res) => {
// Process payment request
});
Balance of security and compatibility: SameSite Cookie provides basic protection, while CSRF Token can provide additional security layers when needed.