14

以下引用来自http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html

当用户访问一个站点时,该站点应该生成一个(加密性强的)伪随机值,并将其设置为用户机器上的 cookie。该站点应要求每个表单提交都包含此伪随机值作为表单值和 cookie 值。当一个 POST 请求被发送到站点时,只有当表单值和 cookie 值相同时,该请求才被认为是有效的。当攻击者代表用户提交表单时,他只能修改表单的值。根据同源策略,攻击者无法读取从服务器发送的任何数据或修改 cookie 值。这意味着虽然攻击者可以通过表单发送他想要的任何值,但他将无法修改或读取存储在 cookie 中的值。由于 cookie 值和表单值必须相同,

上述方法通过比较cookie和表单中的伪随机值来防止CSRF攻击。但是,为什么还需要将值与表单一起返回?我假设表单和 cookie 都具有它们返回到服务器的相同加密值。服务器通过解密该值来验证它。

因此,即使该值仅由 cookie 返回,服务器也可以对其进行解密并验证请求。用表单返回加密值的目的是什么?

4

2 回答 2

53

好的,让我们将问题分解为原子问题以便更好地理解:

这个 CSRF 是什么?

这是一种 Web 应用程序漏洞。在最基本的层面上,CSRF 的原因是浏览器不知道如何区分用户是否故意执行操作(例如通过单击表单上的按钮或单击超链接等)或者是否用户在不知不觉中执行了该操作(例如,用户访问了某个域的页面,例如 bad.com,并且当用户已经登录到 good.com 时,bad.com 向 good.com/some_action 发送了请求)。

那么CSRF的影响是什么

现在让我们用 facebook.com 替换上面的 good.com。假设当用户登录 facebook.com 在他的墙上发表评论时,会发送一个 HTTP GET 请求,格式为
https://facebook.com/postComment?userId=Abhinav_123&comment= HiIAmAbhinav。

现在让我们假设用户在他仍然登录到 facebook.com 时访问了 bad.com 上的一个页面。现在 bad.com 属于攻击者,他在 bad.com 上编写了以下代码:

<img src="https: //facebook.com/postComment?userId=Abhinav_123&comment=I_AM_AN_IDIOT>

现在,只要用户的浏览器在 bad.com 上加载此页面的内容,就会向 facebook.com 发送一个请求,如下所示:

https://facebook.com/postComment?userId=Abhinav_123&comment=I_AM_AN_IDIOT

因为浏览器会尝试渲染 img 标签。为此,它需要获取 src 中指定的资源,因此它会发送上述 HTTP GET 请求。因此,基本上攻击者实际上可以代表用户向 facebook.com 提交请求,而他实际上并不知道这一点。

现在有什么可能阻止这种攻击?

如果只有某种方法可以确定请求是否是用户故意提出的。因此,为了做到这一点,反 CSRF 令牌出现了。它只是一个随机的、唯一的字符串,由服务器(上面示例中的 facebook.com)生成并发送给用户并在用户的浏览器中设置为 cookie。现在,对于涉及某些敏感操作的每个请求(例如在上面的 facebook 示例中发布评论),浏览器也会将此随机字符串与请求一起发送,并且服务器在执行操作之前将验证随机字符串是否是它所拥有的是否发送到浏览器。

这个想法是攻击者不会知道这个随机字符串。因此,即使攻击者创建了一个如上所示的 img src,并且用户访问 bad.com,也不会执行(在我们上面的示例中发布评论)的操作,因为除了 URL 之外,要执行的操作,还需要一个额外的东西,就是攻击者没有的随机字符串。

但是再次在 cookie 中设置这个随机字符串有一个巨大的缺陷

由于 cookie 的设计方式和浏览器处理 cookie 的方式,在 cookie 中设置这个随机字符串(反 CSRF 令牌)将无法达到我们的目的。根据设计,客户端向服务器发出的每个请求都会自动将 cookie 发送到服务器(简而言之,为简单起见省略了详细信息。有关更多详细信息,请参阅:RFC2965

所以,在我们上面的例子中,攻击者并不真的需要知道随机字符串。发布评论操作仍将完成,因为一旦用户访问 bad.com 并加载发布评论 URL(如上所述),随机的反 CSRF 令牌(存在于 cookie 中)将自动伴随请求。

那么解决方案是什么?

服务器(facebook.com)不需要将反 CSRF 令牌放入 cookie 中,而是需要将其作为隐藏参数放入表单中,并在用户请求发表评论时制作此表单(持有反 CSRF 令牌)也应该张贴。

现在攻击者无法代表用户执行此敏感操作(除非他以某种方式发现了随机的反 CSRF 令牌本身)

现在来到登录CSRF和双重提交cookie的问题

很多时候,网站会通过部署某种形式的 anti_CSRF 令牌架构来保护自己免受 CSRF 攻击。但是很多时候网站并不关心保护他们的登录表单免受 CSRF 攻击。为什么 ?- 因为即使是登录表单也容易受到 CSRF 攻击,并且攻击者试图通过他的域 (bad.com) 向 good.com (facebook.com) 发送登录请求来利用它,用户仍然需要输入他的有效凭据登录 facebook.com。这些凭据仅适用于真正的用户而不是攻击者,因此攻击者无法构建成功的登录请求。

那么这里攻击者的攻击机会是什么?

攻击者可以使用 facebook.com 创建自己的帐户。他现在拥有一套自己的有效凭证。现在,他使用他的登录凭据和他的域 (bad.com) 构建了对 facebook.com 的登录请求。现在,当用户访问页面 bad.com 时,用户已登录到我的帐户。作为被攻击者,我稍后可以看到用户在帐户上执行的所有活动也可能泄露敏感信息(例如,如果用户选择发送新朋友请求,则发送朋友请求,发送给某人的消息,如果用户这样做,则再次发送登录我的帐户后。所有这些可能性都取决于用户是否确信他已经登录了这个自己的帐户,攻击者可以通过使他自己的 facebook 页面看起来与受害者尽可能接近来再次处理这个问题。

那么现在有什么缓解技术呢?

这是我们现在需要的双重提交cookie。

这到底是什么意思

双重提交 cookie 定义为在 cookie 和请求参数中发送一个随机值,服务器验证 cookie 值和请求值是否相等。

它如何帮助减轻攻击?

根据双cookie的实现原理,当匿名用户(未登录的用户)访问登录页面时,服务器会在用户的浏览器中设置一个带有一些随机字符串的cookie,并在请求参数中设置相同的(比如表单隐藏字段)。当用户提交登录请求时,这些东西会随请求一起提交——用户凭据、隐藏表单字段中的随机字符串和保存随机字符串的 cookie(当然会自动发送)。

现在攻击者将可以访问他自己的凭据、服务器在 cookie 中设置的随机字符串以及攻击者的隐藏表单字段。当攻击者将此精心制作的登录请求发送给用户(受害者),并且用户尝试发出此请求时,该用户仍未登录,并且到目前为止是服务器的匿名用户。因此,服务器将在用户浏览器上设置一个 cookie,该 cookie 具有不同的(与攻击者的)随机值。现在当用户通过攻击者制作的链接发出登录请求时,该请求将包含攻击者的凭据,隐藏表单字段中的攻击者随机字符串,但 cookie 中的用户随机字符串(来自用户的浏览器)。现在当这个请求到达服务器时,

所以这也是用表单返回加密值的原因。希望它清除了这个概念。

于 2015-04-14T08:02:43.100 回答
9

Cookie 会随每个请求自动发送,无论该请求是由原始站点还是由第三方站点发起的。这就是为什么单独一个 cookie 是不够的,因为每个请求都会包含它。

但是通过在请求本身中也包含令牌,攻击站点无法再生成有效请求,因为它们无法获取用户的令牌。

于 2012-07-17T08:50:14.843 回答