前端安全系列(二):如何防止CSRF攻击?
字数 1659 2025-08-18 11:37:42

防止CSRF攻击的全面指南

1. CSRF攻击概述

CSRF(Cross-site request forgery)跨站请求伪造是一种网络攻击方式,攻击者诱导受害者进入第三方网站,在第三方网站中向被攻击网站发送跨站请求,利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户执行操作的目的。

典型攻击流程

  1. 受害者登录a.com,并保留了登录凭证(Cookie)
  2. 攻击者引诱受害者访问了b.com
  3. b.com向a.com发送请求:a.com/act=xx,浏览器默认携带a.com的Cookie
  4. a.com验证请求,确认是受害者的凭证,误以为是受害者自己发送的请求
  5. a.com以受害者名义执行act=xx
  6. 攻击完成,攻击者在受害者不知情的情况下冒充受害者执行操作

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的方法

  1. 在CSP设置
  2. 页面头部增加meta标签
  3. a标签增加referrerpolicy属性

Referer不可信的情况

  • 攻击者设置referrerpolicy="no-referrer"
  • IE6、7下使用window.location.href或window.open跳转
  • HTTPS跳转到HTTP页面
  • Flash跳转

3.2 CSRF Token

实现原理

  1. 将CSRF Token输出到页面中
  2. 页面提交请求携带Token
  3. 服务器验证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验证

实现流程

  1. 用户访问网站时注入随机字符串Cookie
  2. 前端请求时将Cookie添加到URL参数中
  3. 后端验证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. 防止网站被利用为攻击源

  1. 严格管理上传接口,防止意外上传内容
  2. 添加Header X-Content-Type-Options: nosniff
  3. 对用户上传图片进行转存或校验
  4. 用户打开他人链接时告知风险

5. CSRF测试与监控

测试工具CSRFTester使用步骤

  1. 设置浏览器代理(默认localhost:8008)
  2. 使用合法账户访问网站开始测试
  3. 修改并伪造请求
  4. 生成报告并修复漏洞

监控特征

  • 跨域请求
  • GET请求Header的MIME类型为图片,实际返回为Text/JSON/HTML

6. 总结防护策略

  1. 自动防御:同源检测(Origin和Referer验证)
  2. 主动防御:Token验证或双重Cookie验证+Samesite Cookie
  3. 保证页面幂等性,不在GET请求中做用户操作

7. 历史案例

WordPress CSRF漏洞(2012)

允许攻击者修改Post标题、添加管理员、操作用户账户等。

YouTube CSRF漏洞(2008)

几乎所有用户操作都存在漏洞,可添加视频到收藏、添加好友、标记视频不宜等。

防止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 链接类型CSRF 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示例代码 分布式校验方案 存储在Redis等公共存储空间 使用Encrypted Token Pattern(计算Token而非随机生成) 3.3 双重Cookie验证 实现流程 用户访问网站时注入随机字符串Cookie 前端请求时将Cookie添加到URL参数中 后端验证Cookie与URL参数是否一致 优点 : 无需使用Session Token储存于客户端 实施成本低 缺点 : Cookie增加额外字段 存在XSS漏洞时可能失效 难以做到子域名隔离 3.4 Samesite Cookie属性 Strict模式 任何跨域请求都不携带Cookie。 Lax模式 GET请求且改变当前页面或打开新页面时可作为第三方Cookie。 Java实现示例 局限性 : 兼容性问题(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) 几乎所有用户操作都存在漏洞,可添加视频到收藏、添加好友、标记视频不宜等。