跨站请求伪造如何拦截

wen 网络安全 26

本文目录导读:

跨站请求伪造如何拦截

  1. 核心防御策略(推荐组合使用)
  2. 哪些方法“不能”拦截CSRF?
  3. 最佳实践组合(推荐)
  4. 代码示例(简单Spring Boot防护)

跨站请求伪造(CSRF)是一种常见的Web安全漏洞,攻击者诱导用户点击链接或访问页面,在用户不知情的情况下,利用用户已登录的身份向目标网站发送恶意请求(如转账、改密),要有效拦截CSRF攻击,通常采用以下后端防御策略(前端无法独立防御CSRF):

核心防御策略(推荐组合使用)

使用 Anti-CSRF Token(最常用、最有效)

  • 原理:服务器为每个会话或每个表单生成一个随机、不可预测的Token,并将其嵌入到表单的隐藏字段或请求头中,服务器验证请求时,检查Token是否合法。
  • 实现方式
    • 表单嵌入:在HTML表单中生成 <input type="hidden" name="_csrf_token" value="随机值">
    • 请求头携带:通过JavaScript从Cookie或页面变量中读取Token,附加到Ajax请求的 X-CSRF-TokenX-XSRF-TOKEN 头中(常见于前后端分离项目,如Spring Security的默认实现)。
  • 关键点:Token必须与用户会话绑定,且攻击者无法伪造(不能通过跨域请求获取)。
  • 注意:不要在GET请求中使用Token(GET请求可能被第三方网站直接触发),只对POST/PUT/DELETE等修改性请求进行验证。

同源检测(Origin / Referer 头验证)

  • 原理:检查HTTP请求头中的 Origin(推荐)或 Referer 字段,判断请求是否来自本站(同源)。
  • 实现
    • 验证 Origin 头是否在允许的白名单中。Origin 是安全头,由浏览器自动添加(仅跨域请求时)。
    • Origin 为空(某些情况下,如HTTPS→HTTP请求可能丢失),可回退验证 Referer
  • 局限性
    • Referer 可能被用户隐私设置禁用,也可能由攻击者在某些漏洞下伪造(低概率)。
    • Origin 相对可靠,但某些旧浏览器不支持。
  • 建议:作为辅助手段,与Token结合使用。

设置 SameSite Cookie 属性(浏览器原生防御)

  • 原理:通过设置Cookie的 SameSite 属性,控制浏览器在跨站请求时是否附带Cookie(默认不携带)。
  • 属性值
    • Strict(严格):所有跨站请求都不发送Cookie(最安全,但用户体验差,如从第三方网站点击链接到本站,Session丢失)。
    • Lax(宽松,现代浏览器默认值):仅允许“顶级导航”GET请求(如点击链接、地址栏输入)发送Cookie,表单POST、Ajax等跨站请求不发送,这是平衡安全与体验的最佳选择。
    • None:禁用SameSite防御,但必须同时设置 Secure(仅HTTPS)。
  • 用法(以Spring Boot为例):response.addHeader("Set-Cookie", "JSESSIONID=xxx; SameSite=Lax; HttpOnly")
  • 注意:仅依靠SameSite还不够,因为有少数请求(如某些GET链接)仍可能携带Cookie,且旧浏览器不支持。

验证 HTTP 请求方法

  • 原理:强制要求状态修改操作(增、删、改)使用POST、PUT、DELETE等安全方法,拒绝GET请求执行修改(因为攻击者容易构造 <img><a> 标签触发GET)。
  • 注意:不是防御CSRF的充分条件,但能消除大部分简单攻击向量。

二次验证(对高风险操作)

  • 原理:对敏感操作(如修改密码、转账、删除账户)不依赖Token,强制用户输入当前密码、短信验证码或图形验证码。
  • 效果:攻击者无法自动完成,极大提高难度。
  • 适用场景:金融、账户管理等关键功能。

哪些方法“不能”拦截CSRF?

  • 仅依赖前端(如JS防点击、验证Referer):攻击者可构造请求绕过前端。
  • 使用Session在URL中传参:能被直接看到,且易泄露(如URL被分享到社交媒体)。
  • 单纯依赖IP/UA/时间戳:这些信息可以被伪造或获取。

最佳实践组合(推荐)

对所有状态修改请求(POST/PUT/DELETE)生成并验证 Anti-CSRF Token(服务端会话绑定)。
2. 在全局过滤器/中间件中验证 Origin 头(或 Referer),作为第二道防线。
3. 将所有Session Cookie设置为 SameSite=Lax(或Strict),并 HttpOnly。
4. 拒绝GET请求做状态修改(RESTful规范遵循)。
5. 对高风险操作(如转账、改密)强制二次验证。

代码示例(简单Spring Boot防护)

生成Token(后端)

@RequestMapping("/form")
public String showForm(HttpServletRequest request, Model model) {
    String csrfToken = UUID.randomUUID().toString();
    request.getSession().setAttribute("CSRF_TOKEN", csrfToken);
    model.addAttribute("csrfToken", csrfToken);
    return "form";
}

验证Token(拦截器)

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    if ("POST".equalsIgnoreCase(request.getMethod())) {
        String sessionToken = (String) request.getSession().getAttribute("CSRF_TOKEN");
        String requestToken = request.getParameter("_csrf_token");
        if (sessionToken == null || !sessionToken.equals(requestToken)) {
            response.sendError(403, "CSRF token mismatch");
            return false;
        }
    }
    return true;
}
  • 最推荐Anti-CSRF Token + SameSite=Lax + Origin验证,三者结合抵御绝大多数CSRF攻击。
  • 核心思想:让攻击者无法伪造合法的请求凭证(Token)或无法附带关键身份凭证(Cookie)。
  • 注意:CSRF防御是后端责任,前端只能辅助(如通过JS读取Cookie中的Token并添加到请求头),但不能作为唯一防线。

抱歉,评论功能暂时关闭!