前端安全系列(二):如何防止CSRF攻击?
字数 1659 2025-08-18 11:37:42
防止CSRF攻击的全面指南
1. CSRF攻击概述
CSRF(Cross-site request forgery)跨站请求伪造是一种网络攻击方式,攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户执行操作的目的。
典型攻击流程
- 受害者登录a.com,并保留了登录凭证(Cookie)
- 攻击者引诱受害者访问了b.com
- b.com向a.com发送请求:a.com/act=xx,浏览器默认携带a.com的Cookie
- a.com验证请求,确认是受害者的凭证,误以为是受害者自己发送的请求
- a.com以受害者名义执行act=xx
- 攻击完成,攻击者在受害者不知情的情况下冒充受害者执行操作
2. CSRF攻击类型
GET类型CSRF
访问含有此img的页面后,浏览器会自动向目标URL发出HTTP请求。
POST类型CSRF
<form action="http://bank.example/withdraw" method="POST">
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
</form>
<script>document.forms[0].submit();</script>
链接类型CSRF
<a href="http://test.com/csrf/withdraw.php?amount=1000&for=hacker" taget="_blank">
重磅消息!!
</a>
3. CSRF防护策略
3.1 同源检测
Origin Header检测
服务器可以解析请求Header中的Origin字段确定来源域名。
局限性:
- IE11同源策略下不会添加Origin标头
- 302重定向后Origin不包含在重定向请求中
Referer Header检测
验证HTTP头中的Referer字段记录请求来源地址。
设置Referrer Policy的方法:
- 在CSP设置
- 页面头部增加meta标签
- a标签增加referrerpolicy属性
Referer不可信的情况:
- 攻击者设置referrerpolicy="no-referrer"
- IE6、7下使用window.location.href或window.open跳转
- HTTPS跳转到HTTP页面
- Flash跳转
3.2 CSRF Token
实现原理
- 将CSRF Token输出到页面中
- 页面提交请求携带Token
- 服务器验证Token是否正确
Java示例代码
HttpServletRequest req = (HttpServletRequest)request;
HttpSession s = req.getSession();
String sToken = (String)s.getAttribute("csrftoken");
if(sToken == null){
sToken = generateToken();
s.setAttribute("csrftoken",sToken);
chain.doFilter(request, response);
} else{
String xhrToken = req.getHeader("csrftoken");
String pToken = req.getParameter("csrftoken");
if(sToken != null && xhrToken != null && sToken.equals(xhrToken)){
chain.doFilter(request, response);
}else if(sToken != null && pToken != null && sToken.equals(pToken)){
chain.doFilter(request, response);
}else{
request.getRequestDispatcher("error.jsp").forward(request,response);
}
}
分布式校验方案
- 存储在Redis等公共存储空间
- 使用Encrypted Token Pattern(计算Token而非随机生成)
3.3 双重Cookie验证
实现流程
- 用户访问网站时注入随机字符串Cookie
- 前端请求时将Cookie添加到URL参数中
- 后端验证Cookie与URL参数是否一致
优点:
- 无需使用Session
- Token储存于客户端
- 实施成本低
缺点:
- Cookie增加额外字段
- 存在XSS漏洞时可能失效
- 难以做到子域名隔离
3.4 Samesite Cookie属性
Strict模式
Set-Cookie: foo=1; Samesite=Strict
任何跨域请求都不携带Cookie。
Lax模式
Set-Cookie: bar=2; Samesite=Lax
GET请求且改变当前页面或打开新页面时可作为第三方Cookie。
Java实现示例
private void addTokenCookieAndHeader(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
String sToken = this.generateToken();
String CookieSpec = String.format("%s=%s; Path=%s; HttpOnly; Samesite=Strict",
this.determineCookieName(httpRequest), sToken, httpRequest.getRequestURI());
httpResponse.addHeader("Set-Cookie", CookieSpec);
httpResponse.setHeader(CSRF_TOKEN_NAME, token);
}
局限性:
- 兼容性问题(Safari等不支持)
- 不支持子域
4. 防止网站被利用为攻击源
- 严格管理上传接口,防止意外上传内容
- 添加Header
X-Content-Type-Options: nosniff - 对用户上传图片进行转存或校验
- 用户打开他人链接时告知风险
5. CSRF测试与监控
测试工具CSRFTester使用步骤
- 设置浏览器代理(默认localhost:8008)
- 使用合法账户访问网站开始测试
- 修改并伪造请求
- 生成报告并修复漏洞
监控特征
- 跨域请求
- GET请求Header的MIME类型为图片,实际返回为Text/JSON/HTML
6. 总结防护策略
- 自动防御:同源检测(Origin和Referer验证)
- 主动防御:Token验证或双重Cookie验证+Samesite Cookie
- 保证页面幂等性,不在GET请求中做用户操作
7. 历史案例
WordPress CSRF漏洞(2012)
允许攻击者修改Post标题、添加管理员、操作用户账户等。
YouTube CSRF漏洞(2008)
几乎所有用户操作都存在漏洞,可添加视频到收藏、添加好友、标记视频不宜等。