A typical scenario of CSRF attack
CSRF (Cross-Site Request Forgery) attack is a type of attack that exploits a user's logged-in identity to perform unintended actions without their knowledge. Attackers forge requests to trick users or browsers into sending malicious requests, thereby bypassing authentication mechanisms.
Basic Principles of CSRF Attacks
The core of a CSRF attack lies in exploiting the browser's automatic cookie-carrying mechanism. When a user logs into a website, the browser stores session cookies and automatically attaches these cookies to subsequent requests. Attackers construct a malicious page or link to lure users into visiting it, thereby triggering a cross-site request. Since the request carries the user's legitimate cookies, the server mistakenly believes it is a legitimate action initiated by the user.
A typical attack flow is as follows:
- The user logs into a trusted website A and saves the session cookie.
- The user visits a malicious website B without logging out.
- Website B's page contains code (such as a form or script) that initiates a request to website A.
- The browser automatically sends the request with website A's cookies, and the website A server treats it as a legitimate user action.
Examples of Typical Attack Scenarios
Scenario 1: Modifying Data via GET Requests
Assume a bank's transfer function uses a GET request with the following URL:
https://bank.example/transfer?to=attacker&amount=1000
An attacker can embed an image tag in a malicious website:
<img src="https://bank.example/transfer?to=attacker&amount=1000" width="0" height="0">
When the user visits this page, the browser automatically loads the image and sends the GET request to complete the transfer.
Scenario 2: Forging Requests via Form Submission
If the bank switches to POST requests but does not protect against CSRF, the attacker can construct a hidden form:
<form action="https://bank.example/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit();</script>
When the user visits the page, the form is automatically submitted.
Scenario 3: CSRF Exploiting JSON APIs
Modern applications often use JSON APIs, but if CORS is not properly configured, they may still be vulnerable. For example:
fetch('https://api.example/change-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'attacker@example.com' }),
credentials: 'include' // Automatically includes cookies
});
An attacker can directly send this request from a malicious page.
High-Risk Operations and Sensitive Interfaces
The following types of interfaces are highly susceptible to CSRF attacks:
- Modifying user information (password, email, phone number)
- Financial operations (transfers, payments)
- Data deletion (clearing shopping carts, deleting accounts)
- Permission changes (elevating user roles)
For example, a social media site's "delete account" interface:
POST /api/account/delete HTTP/1.1
A simple forged request can result in account deletion.
Implementation Details of Defense Measures
Same-Origin Detection: Origin and Referer Validation
The server should validate the Origin
or Referer
headers:
// Node.js example
app.post('/transfer', (req, res) => {
const origin = req.get('Origin');
if (origin !== 'https://yourdomain.com') {
return res.status(403).send('Forbidden');
}
// Process normal logic
});
CSRF Token Mechanism
- Generate Token:
// Server generates and stores the token
const csrfToken = crypto.randomBytes(32).toString('hex');
session.csrfToken = csrfToken;
- Frontend Carries Token:
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<!-- Other form fields -->
</form>
- Server Validation:
app.post('/transfer', (req, res) => {
if (req.body._csrf !== session.csrfToken) {
return res.status(403).send('Invalid CSRF token');
}
// Process normal logic
});
SameSite Cookie Attribute
Set the SameSite
attribute for sensitive cookies:
Set-Cookie: sessionId=abc123; SameSite=Strict; Secure; HttpOnly
Strict
: Completely blocks third-party cookiesLax
: Allows cross-site requests with safe methods (e.g., GET)
Double Cookie Verification
- Frontend reads the token from the cookie:
function getCookie(name) {
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
const csrfToken = getCookie('csrfToken');
- Attach it to the request header:
fetch('/api/transfer', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': csrfToken
}
});
Built-in Framework Protections
Express's csrf Middleware
const csrf = require('csurf');
app.use(csrf({ cookie: true }));
// Inject token into views
app.get('/form', (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
Django's CSRF Protection
Automatically adds tokens in templates:
<form method="post">
{% csrf_token %}
<!-- Form content -->
</form>
Spring Security Configuration
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
Protection in Special Scenarios
Single-Page Application (SPA) CSRF Protection
For frontend-backend separation architectures:
- The server sets a
SameSite=Lax
cookie. - The frontend retrieves the CSRF token from the initial response:
// Login response example
{
"user": {...},
"csrfToken": "a1b2c3d4"
}
- Subsequent requests carry it in the header:
axios.defaults.headers.common['X-CSRF-Token'] = storedCsrfToken;
CSRF Protection for File Uploads
Traditional form uploads require special handling:
<form enctype="multipart/form-data">
<input type="hidden" name="_csrf" value="token">
<input type="file" name="file">
</form>
Limitations of Defense Measures
- Token Leakage: If an XSS vulnerability exists, attackers can steal tokens.
- Subdomain Risks: Different subdomains under the same site may share cookies.
- Browser Compatibility: Older browsers may not support SameSite.
Real-World Case Studies
Case 1: Social Media Follow Hijacking
A platform's follow API lacked CSRF protection:
POST /api/follow HTTP/1.1
Host: social.example
Cookie: session=valid_session
{"userId":"attacker"}
Attackers constructed a page to automatically send this request, causing users to follow malicious accounts.
Case 2: E-commerce Platform Price Tampering
A product modification interface lacked protection:
fetch('/admin/products/123', {
method: 'PUT',
body: JSON.stringify({ price: 0.01 })
});
Attackers could trick administrators into visiting malicious pages to alter product prices.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:CSRF 攻击的基本原理
下一篇:CSRF 与 XSS 的区别