您现在的位置是:网站首页 > CSRF 攻击的基本原理文章详情
CSRF 攻击的基本原理
陈川
【
前端安全
】
20734人已围观
3578字
CSRF 攻击的定义与核心逻辑
跨站请求伪造(CSRF)是一种利用用户已登录状态,在用户不知情时以用户名义执行非预期操作的攻击方式。攻击者诱导用户访问恶意页面时,该页面携带伪造请求访问目标站点,由于浏览器会自动携带用户的认证信息(如Cookie),服务器会误认为是用户发起的合法请求。核心逻辑在于跨域请求+身份验证漏洞的组合利用。
典型场景:用户登录银行网站A后未登出,访问恶意网站B,B的页面隐藏了一个向A发起转账的请求,浏览器自动携带A的Cookie完成请求。
攻击的必要条件
-
身份验证依赖浏览器自动提交的凭证
常见于Cookie、Basic Auth等机制,例如:// 服务器设置登录态Cookie Set-Cookie: sessionid=abc123; HttpOnly; Secure
-
请求参数可预测
攻击者能构造出完整请求,如转账接口/transfer?to=attacker&amount=1000
的参数结构公开。 -
目标站点未校验请求来源
服务器未验证Origin
或Referer
头,例如:POST /transfer HTTP/1.1 Host: bank.com Cookie: sessionid=abc123 Content-Type: application/x-www-form-urlencoded to=attacker&amount=1000
常见攻击载体与示例
自动提交表单
<!-- 恶意页面隐藏表单 -->
<body onload="document.forms[0].submit()">
<form action="https://bank.com/transfer" method="POST">
<input type="hidden" name="to" value="attacker">
<input type="hidden" name="amount" value="10000">
</form>
</body>
图片标签GET请求
<!-- 利用img标签自动发送GET请求 -->
<img src="https://bank.com/delete-account?id=123" width="0" height="0">
AJAX请求(受同源策略限制但仍有风险)
// 如果服务器允许任意Origin,仍可能成功
fetch('https://bank.com/change-email', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({email: 'attacker@evil.com'})
});
防御策略的技术实现
同源检测
// 中间件校验Referer头
app.use((req, res, next) => {
const referer = req.get('Referer');
if (!referer || !referer.startsWith('https://yourdomain.com')) {
return res.status(403).send('Invalid request source');
}
next();
});
CSRF Token
<!-- 服务端渲染时嵌入Token -->
<form action="/transfer" method="POST">
<input type="hidden" name="_csrf" value="随机字符串">
<!-- 其他表单字段 -->
</form>
// 服务端验证示例
app.post('/transfer', (req, res) => {
if (req.body._csrf !== req.session.csrfToken) {
return res.status(403).send('CSRF token invalid');
}
// 处理正常业务
});
SameSite Cookie属性
Set-Cookie: sessionid=abc123; SameSite=Strict; HttpOnly; Secure
双重Cookie验证
// 前端从Cookie读取token并放入请求头
const token = document.cookie.match(/csrftoken=([^;]+)/)[1];
fetch('/api/action', {
method: 'POST',
headers: { 'X-CSRF-TOKEN': token }
});
特殊场景下的防护考量
单页应用(SPA)的Token管理
// 初始加载时获取Token
let csrfToken = '';
fetch('/api/csrf-token', { credentials: 'include' })
.then(res => res.json())
.then(data => { csrfToken = data.token; });
// 后续请求携带Token
function safeFetch(url, options) {
options.headers = {
...options.headers,
'X-CSRF-Token': csrfToken
};
return fetch(url, options);
}
文件上传的防护
<!-- 需要为multipart表单单独处理 -->
<form enctype="multipart/form-data">
<input type="hidden" name="_csrf" value="token">
<input type="file" name="file">
</form>
历史漏洞案例分析
2018年某社交平台CSRF漏洞导致用户关系被篡改,攻击者构造如下页面:
<script>
function exploit() {
fetch('https://social.com/api/follow', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({userId: 'attacker'})
});
}
setTimeout(exploit, 3000);
</script>
漏洞成因:API未校验Content-Type为application/json
的请求来源,且未使用CSRF Token。
与其他安全机制的协同
与CORS策略的关系
Access-Control-Allow-Origin: https://trusted.com
Access-Control-Allow-Credentials: true
即使正确配置CORS,仍需CSRF防护,因为:
- 简单请求(GET/POST表单)不触发预检
- 恶意页面可能通过表单而非AJAX发起请求
与XSS防护的关联
Set-Cookie: sessionid=abc123; HttpOnly; Secure; SameSite=Strict
XSS漏洞可能导致CSRF Token被窃取,因此必须配合内容安全策略(CSP):
Content-Security-Policy: script-src 'self'
上一篇: 自动化检测与工具推荐
下一篇: CSRF 攻击的典型场景