什么是 CSRF 跨站请求伪造

Posted on Wed, 25 Dec 2024 10:33:13 +0800 by LiangMingJian


概述

‌CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络攻击方式,其主要通过诱导用户在目标网站点击恶意链接,利用用户的身份和权限,在用户不知情的情况下向目标网站发起非用户本意的请求,执行未授权操作。

比如,在 A 站这样的一个恶意链接,这个链接在点击后会获取当前登录用户的 Cookie 或者 Session,然后发送 A 站点中重置密码的请求。当用户在不知情的情况下点击这个恶意链接时,那么这名用户的密码就会被重置。

‌攻击原理

用户已登录目标网站,在浏览器中保存了登录信息,这个是基础‌

因为 CSRF 是通过目标网络上恶意链接进行攻击的,那么当攻击时,就需要获取包含用户身份信息的会话令牌(Cookie、Session)才能执行一些具有攻击性的操作。

诱导访问恶意链接,伪造请求,这个是触发条件

恶意链接的访问触发有下面两种情况,一种是点击目标网站 A 上的恶意链接,一种是点击恶意网站 B 上指向目标网站 A 的恶意链接。

攻击者会通过各种手段,诱导用户去点击一个目标网站 A 上的恶意链接,因为用户在目标网站 A 上是登录的,因此当访问这个恶意链接时,浏览器会自动给请求添加登录信息(Cookie、Session),进而实现攻击。比如通过分享一个资源链接,但这个资源链接实际是一个恶意链接,可以用来进行攻击。

或者,用户访问了一个恶意网站 B,这个网站 B 中有着一个指向目标网站 A 的恶意链接,当用户点击这个链接后,一些目标网站 A 的请求会在不知情的情况下发送到 A,此时,由于 A 中残留了用户的登录信息,所以浏览器会自动给这些请求添加登录信息(Cookie、Session),进而实现攻击。

服务器误判,这个是最终结果‌

最后,当目标网站收到请求后,会因为 Cookie、Session 有效,误认为是用户主动发起的合法操作,从而执行攻击者指定的行为,完成攻击。

简而言之,要完成一次 CSRF 功能,用户必须完成以下两个步骤:

  • 第一:在目标网站 A 上已经登录了,并且 Cookie、Session 以保存在浏览器本地。
  • 第二:在 A 登录的前提下,点击了 A 上的恶意链接,或者在恶意网站 B 上点击了指向 A 的恶意链接。

‌防御手段

CSRF Token

由于 CSRF 攻击是因为服务器把攻击者携带的 Cookie 当成正常的用户请求,那么如果我们可以要求所有用户请求都必须携带一个无法被攻击者劫持的 token,服务端通过校验这个 token 就可以防止 CSRF 攻击。

简而言之,CSRF Token 就是只有当用户在访问页面时,服务器会给用户随机生成一个 Token。这个 Token 往往会是随机字符串和时间戳的组合,在提交时,这个 Token 需要单独附加到请求后面,不能保存在 Cookie 中,避免攻击者利用。最终服务器通过校验这个 Token 的正确性,来判断请求是否合法。

这是最常用的 CSRF 防御方法,现在市场上大部分 Web 开发服务器架构都支持启用 CSRF Token 防御机制。

比如,Django 架构的 {% csrf_token %} 标签,Spring 架构的 HttpSessionCsrfTokenRepository,以及 Laravel 架构的 @csrf。

验证 Referer‌

浏览器在发送请求时,往往会在请求头携带一个 Referer,用来标识这个请求是从哪里来的,服务器可以通过检查这个请求头,来确认请求是否来自目标网站,确保安全。

使用 SameSite Cookie‌

将 Cookie 的 SameSite 属性设置为 Strict 或 Lax,来限制 Cookie 在跨站请求中的发送。

从 Chrome 51 版本开始,浏览器的 Cookie 新增了一个 SameSite 属性,其作用是用来防止 CSRF 攻击。

Samesite 属性支持设置三个值:Strict,Lax 和 None。

其中,Strict 最为严格,完全禁止第三方 Cookie,任何情况都不会随请求发送 Cookie;Lax 限制宽松,大多数情况下不随请求发送 Cookie 的,除了链接、预加载请求和 GET 表单; None 表示关闭 SameSite。