CSRF 基本上是指攻击者通过浏览器中 cookie 的工作方式来利用用户的现有会话。根本问题是,无论请求来自何处(哪个来源,即域),都会随请求发送 cookiefrom,唯一重要的是它去了哪里to。因此,如果有用户登录到应用程序(具有会话 cookie),攻击者可能会尝试让该用户访问他的恶意网站,攻击者可以从该网站使用用户的凭据向应用程序域发出请求(通过完全将用户发布到应用程序,或者更巧妙地通过创建 ajax 请求)。
请注意,这仅适用于应用程序中的身份验证基于浏览器自动发送的内容(最明显的是会话 cookie)的情况,但例如基本的 http 身份验证或客户端证书身份验证也可能存在漏洞。此外,CSRF 仅适用于更改某些内容(状态或数据)的请求。
有一个重要的因素在发挥作用,同源策略(SOP)就是浏览器。有点简单,这意味着如果从一个域(或更准确地说:源)下载某些内容,则另一个域将无法访问。
因此,为了防止上述攻击并防止攻击者在自己的域上让用户向用户登录的应用程序发送不需要的请求,可能有几种不同的策略。
同步器令牌
应用程序生成一个 csrf 令牌,将其存储在用户的会话(服务器端)中,并将其发送到客户端,例如将其写入隐藏字段中的每种表单中,或者写入 Javascript 可以读取的单个字段中并添加到请求中。这是可行的,因为其域中的攻击者无法使用用户会话中的有效令牌创建表单或请求,而且攻击者也无法从应用程序页面读取令牌。当然,攻击者可以尝试下载申请表来获取令牌,但随后他需要凭据。攻击者需要有效的用户会话和相应的 csrf 令牌。攻击者可能有自己合适的帐户来登录,但无论如何他都可以执行操作。或者他可能拥有 csrf 令牌,但未经身份验证,或者权限较低的帐户。但他不能两者兼得,这就是重点。
因此,这种保护基本上验证了请求是否来自实际由合法应用程序而不是其他人呈现的源。
请注意,在这种情况下,在 cookie 中设置令牌是没有意义的,因为 cookie 将像会话 cookie 一样自动发送。
重复发帖
另一种策略是生成令牌,并将其设置为客户端的 cookie。然后,客户端从 cookie 中读取令牌,并发送相同的令牌作为请求标头。服务器只比较请求头和cookie中是否包含相同的token。这是可行的,因为攻击者无法从不同来源设置的 cookie 中读取应用程序令牌(请参阅上面的 SOP),但合法域上的应用程序可以。因此发送请求的客户端有效地证明了它正在合法的应用程序域上运行。这样做的好处是应用程序是无状态的,不需要会话。缺点是安全性稍差。
(有趣的是,这种情况下的令牌甚至可以在客户端生成,它仍然有效,因为攻击者在自己的域上无法设置或读取应用程序域 cookie,但它肯定不太安全,因为它是在浏览器。)
检查引用者或来源
正如您正确指出的那样,另一种策略可能是检查请求的引用者或来源。它基本上可以工作,但被认为不太安全。虽然双重发布对于许多应用程序来说被认为足够安全,但引用/来源检查大多不是。我认为它有很强的历史元素,但它确实is不太安全。
这个问题有很多方面,我想到了一些:
- 发送引用/来源标头可以预防 http://geekthis.net/post/hide-http-referer-headers/由攻击者在他自己的域上进行。因此应用程序不会知道它是一个不同的域 - 它只是没有信息。您当然可以以需要引用者和/或来源的方式实现它,但这会导致潜在的错误和问题,即浏览器由于某种原因不发送它等。
- 在某些情况下,Referer 和 origin 可能是伪造的。例如,旧的易受攻击的浏览器插件(Java、Flash...还有人记得 Flash 吗?)允许设置任何标头,攻击者只需要在受害者浏览器中安装其中一个 - 每个人都有它们。
- 浏览器扩展还可以设置/修改标头,因此攻击者可能会尝试让受害者用户安装他的恶意扩展。
- Origin 仅由现代浏览器设置。现在问题已经不大了,大多数人都使用同时设置引用者和来源的浏览器。
因此,出于这些原因,简单地检查引用/来源并不是很可靠,应该采取另一层保护。
同站点 cookies
A new invention by Google in Chrome is the SameSite
attribute to cookies (in addition to the already existing and widespread httpOnly
and secure
cookie attributes). As of now, it is only supported by Chrome and not other browsers. [See update below!]
如上所述,根本问题是 cookie(即会话 cookie)根据请求目标而不是源发送到服务器。这意味着,如果attacker.com向用户提供一个页面,并且该页面从浏览器向legitapp.com发送post请求,则legitapp.com设置的任何cookie都将被发送到legitapp.com。因此,如果是登录legitapp.com的用户访问attacker.com,则现有会话就可以被利用。
这被改变了SameSite cookie 属性 https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/,这使得在源域与目标域不同的情况下不会发送 cookie。它可以设置为“严格”或“宽松”,这基本上决定了 GET 请求行为,但其中任何一个都会阻止 CSRF
非 GET 请求。
2023 年更新:
上述所有内容仍然适用,除了 SameSite 获得主流采用外,所有主流浏览器现在都支持此属性。现在应该将 SameSite 设置为宽松或严格,除非有充分理解的理由不这样做。松懈携带风险多一点 https://portswigger.net/web-security/csrf/bypassing-samesite-restrictions,但提供更好的用户体验。对于许多站点或应用程序,仅 SameSite 可能就足以实现 CSRF 保护,但请确保您完全了解相关风险。