CSRF攻击与防御详解

CSRF(跨站请求伪造) 是一种常见且危险的Web安全漏洞。

核心概念:

CSRF 攻击利用的是 Web 应用程序对用户浏览器的信任。攻击者诱骗受害者在已经通过目标网站(例如银行网站、社交网络、Web 邮件服务)身份验证的情况下,执行一个他们本无意执行的操作(如转账、更改密码、发布状态、发送邮件)。

攻击原理与流程:

  1. 用户登录: 受害者用户使用其凭据(用户名/密码)成功登录到一个可信赖的网站(例如 https://bank.com)。该网站验证用户身份后,会在用户的浏览器中设置一个会话 Cookie(例如 SESSIONID=abc123)。这个 Cookie 标记了用户的登录状态。
  2. 保持登录状态: 只要用户不主动退出或会话未过期,浏览器在后续向 bank.com 发出的每一个请求中,都会自动带上这个会话 Cookie。服务器通过验证这个 Cookie 来识别用户身份并授权操作。
  3. 受害者访问恶意网站: 在保持对 bank.com 登录状态的同时,受害者被诱导访问了攻击者控制或植入恶意代码的网站(例如 https://evil.com)。这种诱导方式可能是通过钓鱼邮件、社交媒体链接、恶意广告、甚至被篡改的正常网站等。
  4. 恶意请求构造: https://evil.com 的页面中包含精心构造的、指向目标网站(bank.com)的恶意请求。这个请求旨在执行一个敏感操作(例如,向攻击者账户转账)。请求的形式可以是:
    • 自动提交的隐藏表单:
      <form action="https://bank.com/transfer" method="POST" style="display: none;">
        <input type="hidden" name="amount" value="1000">
        <input type="hidden" name="toAccount" value="ATTACKER_ACCOUNT_NUM">
        <input type="submit" value="Click for free money!"> <!-- 用户可能看不到或不小心点击 -->
      </form>
      <script>document.forms[0].submit();</script> <!-- 自动提交 -->
      
    • 自动加载的图片/Script标签(常用于 GET 请求):
      <img src="https://bank.com/transfer?amount=1000&toAccount=ATTACKER_ACCOUNT_NUM" width="0" height="0">
      
    • AJAX 请求(受 CORS 限制,但某些简单请求或规避方式仍可能成功): 现代浏览器严格的 CORS 策略使得纯 AJAX CSRF 攻击难度增大,但并非完全不可能,尤其对于允许简单请求(GET/POST with certain headers/content-types)的端点。
  5. 浏览器发送恶意请求: 当受害者访问 evil.com 时,浏览器会加载并执行页面中的恶意代码。浏览器会向 bank.com/transfer 端点发送一个请求(无论是表单提交还是图片加载)。
  6. 携带会话 Cookie: 关键点来了!因为受害者之前已经登录了 bank.com,并且会话 Cookie 仍然有效且属于 bank.com 域,浏览器在发送这个恶意请求时,会自动、静默地将用户的 SESSIONID=abc123 Cookie 附加到请求中。
  7. 服务器处理请求: bank.com 的服务器收到这个请求:
    • 它检查请求中的 Cookie:SESSIONID=abc123
    • 它验证这个 Cookie 是有效的,对应一个已登录的用户(受害者)。
    • 服务器认为这是一个来自合法用户的、经过授权的请求(因为它有有效的会话令牌)。
    • 服务器执行请求指定的操作:将受害者的 1000 元转账到攻击者的账户。
  8. 攻击成功: 攻击者成功利用受害者的登录状态和浏览器的自动 Cookie 发送机制,在受害者不知情且未同意的情况下,执行了敏感操作。

CSRF 攻击成功的关键要素:

  1. 用户身份验证: 用户必须在目标站点上拥有活跃的登录会话(有效的 Cookie)。
  2. 基于 Cookie 的会话管理: 目标应用程序依赖 Cookie 来跟踪用户的会话状态。
  3. 无状态的 HTTP: HTTP 协议本身是无状态的,每个请求独立处理。服务器仅根据请求中包含的信息(如 Cookie)来判断请求者的身份和权限。
  4. 可预测的操作: 攻击者能够构造出执行敏感操作的请求(知道 URL、参数、方法)。
  5. 浏览器行为: 浏览器会在请求同源(或满足特定条件)的资源时,自动附加该源的所有有效 Cookie,无论请求的来源页面是哪里。这是核心机制。

CSRF 与 XSS 的区别:

虽然都是客户端攻击,但原理截然不同:

特性 CSRF (跨站请求伪造) XSS (跨站脚本攻击)
目标 利用用户对目标站点的信任和登录状态。 破坏用户对目标站点的信任。
核心 伪造用户请求。 在目标站点注入并执行恶意脚本。
受害者 受害者浏览器代表用户执行操作 受害者的浏览器执行恶意代码
信任来源 服务器信任用户的浏览器发送的合法会话令牌。 用户的浏览器信任来自目标站点的脚本。
影响范围 执行用户在目标站点能执行的操作。 窃取 Cookie/会话、记录按键、DOM 操作等。
所需条件 用户已登录目标站点并访问恶意页面。 目标站点存在注入漏洞(输入未过滤/转义)。

防御措施:

防止 CSRF 的核心思路是让服务器能够区分哪些请求是用户真正有意发出的,哪些是伪造的。常用方法:

  1. CSRF Tokens (最常用且最有效):

    • 服务器在为用户生成表单(或页面)时,嵌入一个唯一的、不可预测的、与用户会话绑定的令牌(通常是一个长随机字符串)。这个令牌应该存储在服务器端(如 Session)并与用户会话关联。
    • 当用户提交表单(或发起敏感请求,如 POST/PUT/DELETE)时,必须将这个 CSRF Token 包含在请求中(通常作为隐藏表单字段或自定义 HTTP Header,如 X-CSRF-Token)。
    • 服务器在处理请求前,验证提交的 Token 是否与当前用户会话中存储的 Token 匹配,且有效。
    • 为什么有效? 攻击者无法从 evil.com 读取用户当前在 bank.com 页面上生成的 Token(受同源策略保护),因此无法在伪造的请求中包含正确的 Token。服务器会拒绝缺少或 Token 不匹配的请求。
    • 关键点: 确保 Token 足够随机、绑定会话、安全传输(建议通过 POST body 或自定义 Header,避免放在 URL 中)、对每个敏感请求都验证。
  2. SameSite Cookie Attribute (现代浏览器支持):

    • 在设置会话 Cookie 时,指定 SameSite 属性。
    • SameSite=Strict: 浏览器只会在请求 URL 与 Cookie 来源站点完全一致(同站)时才发送 Cookie。这意味着从 evil.com 发起的对 bank.com 的请求绝对不会携带 bank.com 的会话 Cookie。最严格,但可能影响跨站合法链接的用户体验(用户从邮件链接点回银行网站需要重新登录)。
    • SameSite=Lax (现代浏览器的默认行为): 允许在安全的 HTTP 方法(如 GET)且是顶级导航(用户点击链接)时发送 Cookie 到跨站站点。但对于会改变状态的请求(如 POST),仍然只在同站请求中发送。这能阻止大多数 CSRF POST 攻击(如图片 GET 攻击可能仍存在,但危害通常较小)。
    • 为什么有效? 直接限制了浏览器在跨站请求中自动发送 Cookie 的行为,从根本上切断了 CSRF 攻击的依赖路径。
  3. 检查 Origin / Referer Header:

    • 服务器在处理敏感请求时,检查 HTTP 请求头中的 OriginReferer 字段。
    • Origin 指示了请求发起的源(协议+域名+端口)。Referer 指示了请求来源页面的完整 URL。
    • 服务器验证这些 Header 的值是否与应用程序预期的合法源(自己的域名)匹配。如果不匹配或缺失,则拒绝请求。
    • 局限性:
      • 某些隐私设置或浏览器扩展会阻止发送 Referer
      • Referer 可能被篡改(尽管在 HTTPS 上下文中较难)。
      • 从 HTTPS 页面发起到 HTTP 端点的请求,浏览器通常不会发送 Referer
      • 不如 CSRF Token 可靠,通常作为深度防御的辅助手段。
  4. 使用自定义请求头:

    • 对于 AJAX 请求,可以在请求中添加一个自定义的 HTTP Header(例如 X-Requested-With: XMLHttpRequest)。
    • 服务器检查请求中是否包含这个特定的 Header。
    • 为什么有效? 受浏览器的同源策略限制,evil.com 上的脚本无法通过标准的 XMLHttpRequestfetch API 向 bank.com 发送带有自定义头的跨域请求(会触发 CORS 预检并被 bank.com 拒绝,除非 bank.com 显式允许 evil.com 的域发送该头,而这通常不会发生)。
    • 局限性: 仅适用于 AJAX 调用。传统的表单提交或 <img> 标签发起的 GET 请求无法添加自定义 Header。同样受 CORS 策略保护。
  5. 要求重新认证:

    • 在执行极其敏感的操作(如转账、修改密码、更改邮箱)之前,强制要求用户重新输入密码或进行二次认证(如短信验证码)。
    • 为什么有效? 即使 CSRF 攻击成功触发了操作请求,攻击者也无法知道用户的密码或控制用户的二次认证设备,因此无法完成最终的操作授权。
    • 用户体验影响: 可能会降低用户体验流畅度,应权衡安全性和便利性,仅用于最高风险操作。

总结:

CSRF 是一种利用用户浏览器对目标网站的信任和自动发送 Cookie 机制的攻击。攻击者通过诱骗已登录用户访问恶意页面,让用户的浏览器在用户不知情的情况下向目标网站发送伪造的请求,执行恶意操作。

最有效和推荐的防御组合是:

  1. 对所有会改变状态的请求(POST, PUT, DELETE, PATCH)使用 CSRF Tokens。 这是黄金标准。
  2. 为会话 Cookie 设置 SameSite=LaxSameSite=Strict 属性。 利用现代浏览器的内置防护。
  3. (可选/辅助) 检查 Origin/Referer Header 作为额外防护层。
  4. 对最高风险操作实施重新认证。
posted @ 2025-07-03 14:22  bigger_apple  阅读(119)  评论(0)    收藏  举报