请解释 CSRF 攻击的原理和防御方法。

推荐答案

CSRF 攻击原理

CSRF (Cross-Site Request Forgery,跨站请求伪造) 攻击是指攻击者通过伪装成受信任用户的请求,在用户不知情的情况下,以该用户的身份执行恶意操作。其原理简单来说是:

  1. 用户登录受信任网站 A,并保持登录状态(例如,cookie 存储了会话信息)。
  2. 攻击者构造一个恶意请求,该请求的目标是网站 A。
  3. 用户在登录网站 A 的状态下,访问了攻击者构造的恶意页面或链接。
  4. 用户的浏览器在不知情的情况下,发送了攻击者构造的恶意请求到网站 A。
  5. 网站 A 误以为是用户发起的合法请求,从而执行了恶意操作。

CSRF 防御方法

常见的 CSRF 防御方法包括:

  1. 使用 CSRF Token:
    • 服务器在响应中生成一个随机的 token,并将其存储在用户的 session 或 cookie 中。
    • 在每个需要保护的表单或 AJAX 请求中,都包含该 token。
    • 服务器在接收到请求后,验证请求中的 token 是否与 session 或 cookie 中存储的 token 一致,一致则认为是合法请求,否则拒绝。
  2. 使用双重 Cookie 验证 (Double Submit Cookie):
    • 服务器生成一个随机值,同时将其设置在 HTTP-Only 的 cookie 中和 HTML 的隐藏字段中。
    • 客户端发送请求时,隐藏字段的值会被一同发送。
    • 服务器接收到请求后,比较 cookie 中的值和请求参数中的值是否一致,一致则认为是合法请求,否则拒绝。
  3. Referer 检查:
    • 服务器检查请求头中的 Referer 字段,判断请求是否来源于合法的域名。
    • 注意: Referer 字段可能被篡改或缺失,因此不推荐作为主要的防御手段。
  4. 使用验证码:
    • 在敏感操作前,要求用户输入验证码,增加攻击难度。
  5. SameSite Cookie 属性:
    • 设置 SameSite 属性为 StrictLax,可以限制 Cookie 的跨域发送,从而降低 CSRF 攻击风险。
    • Strict 模式下,只有在访问同域网站时才会发送 Cookie;Lax 模式下,会在 GET 请求(例如,点击链接或表单提交)时发送 Cookie,这在实践中常用。

本题详细解读

CSRF 攻击的详细原理

CSRF 的核心在于 “冒充”。攻击者利用用户在目标网站已经建立的信任关系(即登录状态)进行操作。它和 XSS 的区别在于,XSS 利用的是用户对网站的信任,而 CSRF 利用的是网站对用户的信任。

举例说明: 假设有一个银行网站 A,用户登录后可以进行转账操作。

  1. 用户正常登录网站 A,浏览器存储了网站 A 的 cookie。
  2. 攻击者创建了一个恶意网站 B,该网站包含一个隐藏的表单或者一个图片链接,该表单或链接的目的地是网站 A 的转账接口,并附带了攻击者指定的转账金额和收款人信息。
  3. 用户在登录网站 A 的状态下,不小心访问了恶意网站 B。
  4. 当用户访问恶意网站 B 的时候,浏览器自动发送了恶意请求到网站 A,因为请求会默认携带网站 A 的 cookie,网站 A 无法分辨请求是否来自用户本人。
  5. 网站 A 以为是用户本人发起的请求,便执行了转账操作。

常见 CSRF 防御方法的详细解读

1. CSRF Token

  • 原理: CSRF Token 相当于给每个请求都加上一个“验证码”,只有当验证码匹配时,服务器才允许该请求。
  • 实现:
    • 服务器在用户登录成功后,为当前会话生成一个随机的、唯一的 token 值。
    • 将该 token 值保存到服务器的 Session 中。
    • 在页面渲染时,将该 token 值以隐藏字段的形式添加到 HTML 表单中,或者添加到 AJAX 请求的请求头中。
    • 当用户提交表单或发送 AJAX 请求时,浏览器会将隐藏字段或请求头中的 token 值一同发送给服务器。
    • 服务器接收到请求后,首先检查请求中携带的 token 值是否与服务器存储的 session 中的 token 值一致,如果一致,则表示请求是合法的,否则拒绝处理。
  • 优点: 安全性高,能有效防御 CSRF 攻击。
  • 缺点: 需要服务器端进行 token 的生成和验证,实现起来稍微复杂。

2. 双重 Cookie 验证

  • 原理: 将 token 值同时存储在 cookie 中和请求参数中,服务器比对两者是否一致。
  • 实现:
    • 服务器在用户登录后,生成一个随机值。
    • 将该值通过 HTTP-Only 的 Cookie 发送给客户端。
    • 同时,将该值以隐藏字段的形式添加到 HTML 表单中,或通过 JavaScript 动态添加到 AJAX 请求中。
    • 客户端提交表单或发送 AJAX 请求时,会将 Cookie 中的值和隐藏字段中的值一同发送给服务器。
    • 服务器接收到请求后,会比较 Cookie 中值和请求参数中的值是否一致,一致则认为是合法请求,否则拒绝处理。
  • 优点: 实现相对简单,不需要服务器端存储 Session。
  • 缺点: 需要通过 JavaScript 获取 Cookie 值,安全性比 CSRF Token 稍低。

3. Referer 检查

  • 原理: 通过检查 HTTP 请求头中的 Referer 字段来验证请求的来源。
  • 实现:
    • 服务器在接收到请求后,检查 Referer 字段的值,如果该值是来源于自己的域名,则认为是合法请求。
  • 优点: 实现简单
  • 缺点: Referer 字段可以被篡改或缺失,且有些浏览器或用户设置可能不发送 Referer 字段,因此可靠性不高,不能作为主要的防御手段,通常作为辅助防御手段。

4. 验证码

  • 原理: 通过验证码来增加攻击的难度,只有通过验证码校验的请求才会被允许。
  • 实现:
    • 在敏感操作前,要求用户输入验证码。
    • 服务器验证用户输入的验证码是否正确,如果正确,则处理请求。
  • 优点: 可以有效防御自动化 CSRF 攻击
  • 缺点: 用户体验较差,不适合频繁使用。

5. SameSite Cookie 属性

  • 原理: 通过 SameSite 属性来限制 Cookie 的跨域发送,降低 CSRF 攻击的风险。
  • 实现:
    • 在设置 Cookie 时,添加 SameSite 属性:
      • SameSite=Strict: 只有在访问同域网站时才会发送 Cookie。
      • SameSite=Lax: 在 GET 请求(例如,点击链接或表单提交)时发送 Cookie。
      • SameSite=None: 允许跨域发送,需要配合 Secure 属性,仅在 HTTPS 环境下发送。
  • 优点: 可以从根本上阻止某些 CSRF 攻击,实现起来也相对简单。
  • 缺点: 需要浏览器支持,并且部分老旧浏览器可能不支持此属性。
纠错
反馈