6

我已经阅读了很多关于 CSRF 保护的文章(这是一篇很好的文章)以及关于 SO 的各种问题,但它们似乎都没有足够的信息来回答我的问题。

我正在开发自己的 CMS,我想保护我的登录和评论表单。我将允许匿名用户在我的网站上发表评论。

我网站上的所有表格都使用令牌进行保护。我已经知道这种方法,但问题是它需要一个活动会话(即在用户登录之后)。登录和评论表单的问题是几乎任何人都可以访问它们并且不需要您登录 - 在这种情况下,对 CSRF 的最佳保护是什么?

在上面的链接中,我读到可以在用户尝试登录然后继续使用通常的反 CSRF 方法(例如为用户的会话分配令牌)时创建“预会话”,但我不知道如何实现这一目标。

推荐人标头是一个弱解决方案,所以我想我不应该打扰。据我测试,Origin 标头仅在 Google Chrome 中受支持。自定义标题呢?XMLHTTPRequest 似乎是一种可能性,但是,我已经在 Google 上花费了三个多小时来查找有关如何在其网站上实施此类安全措施的一些信息。但是,即使我可以使用自定义标头,由于 HTTP 标头可以完全伪造,它是否会使其无用?

所以,问题是:我应该如何保护我的登录和评论表单免受 CSRF 的影响?

编辑:这是我上面提供的链接中的一些附加信息:

我们建议严格的Referer验证来防止登录CSRF,因为登录表单通常通过HTTPS提交,其中Referer标头可靠地存在于合法请求中。如果登录请求缺少 Referer 标头,则站点应拒绝该请求以防御恶意压制。

秘密验证令牌可以防御登录 CSRF,但开发人员经常忘记实施防御,因为在登录之前,没有会话可以绑定 CSRF 令牌。要使用秘密验证令牌来防止登录 CSRF,站点必须首先创建一个“预会话”,实施基于令牌的 CSRF 保护,然后在成功验证后转换到真正的会话。

在阅读了上述引文后,我无法结束这个论点。其中之一提到使用引用标头,但我不太确定它是否真的增加了 webapp 的安全性。

编辑 2:使用 CAPTCHA 怎么样?

4

4 回答 4

3

CSRF 问题与使用登录用户凭据提交内容的人有关。这是非常有问题的,因为恶意网站可以像任何刚刚浏览过您网站的人一样做事。如果您谈论的是可以匿名使用的表单,而无需登录,那么 CSRF 风险就会大大降低,因为从另一个站点发布到表单的收益要少得多——因为任何人都可以直接使用相同的权限进行操作.

所以我不明白为什么需要针对未登录的表单进行 CSRF 保护。

如果你确实想要这个,会话前令牌在技术上可能类似于真实会话,但只是一个更轻量级的令牌。除了生成的令牌之外,它实际上不包含任何其他内容。


编辑:关于使用 PHP 提供的 $_SESSION 作为会话前令牌,这是 PHP 的标准会话机制。如果你想使用它,那么是的,就是这样。

但是,您不会被迫这样做,而且我个人不会那样做,因为它会消耗所有访问者的服务器内存,而这并不是真正需要的。对于更有效的机制,基本上你需要 a) 一个标识用户的 cookie 和 b) 存储在服务器端的东西,告诉 cookie 是有效的(如果需要,它对谁有效,即 ip)。对于更轻量级的方法,您可以创建一个令牌,将其存储在 cookie 中,并在表单中生成与该令牌匹配的内容作为隐藏字段,并在提交时匹配这些内容(如 Devesh 所解释的)。后者将阻止从另一个站点提交表单,前者甚至可以阻止恶意站点在您的站点上进行查找并尝试向最终用户设置任何 cookie 的情况。所以我能想到的三种方法:

  • 只是阻止来自其他站点的图像请求 - 使用 POST 可以防止这种情况
  • 防止从另一个站点提交表单 - 匹配 cookie 的表单隐藏字段可以防止这种情况
  • 防止从另一个站点提交表单,这些站点在您的站点上进行预查找 - 这需要 IP 验证,存储在服务器端的内容,例如与 cookie 匹配的数据库中的 ip

EDIT2:在验证码上,它们的主要用例是防止自动(蛮力)登录尝试。他们也会解决登录表单上的 CSRF 请求问题,但这样做有点过头了。为了防止暴力登录攻击,在某些情况下可能需要它们,尽管为了不过度降低可用性,可能需要一些更用户友好的东西。也许像KittenAuth :)

于 2013-03-26T08:56:12.593 回答
0

CSRF 问题与使用登录用户凭据提交内容的人有关。这是非常有问题的,因为恶意网站可以像任何刚刚浏览过您网站的人一样做事。如果您谈论的是可以匿名使用的表单,而无需登录,那么 CSRF 风险就会大大降低,因为从另一个站点发布到表单的收益要少得多——因为任何人都可以直接使用相同的权限进行操作.

所以我不明白为什么需要针对未登录的表单进行 CSRF 保护。

如果你确实想要这个,会话前令牌在技术上可能类似于真实会话,但只是一个更轻量级的令牌。除了生成的令牌之外,它实际上不包含任何其他内容。

于 2014-07-05T18:07:02.590 回答
0

我认为您可以通过组合添加到表单中的隐藏字段并同时在 cookie 中添加相同的值并附加用户响应来解决 CSRF 类型的问题。当用户发回表单时,尝试匹配隐藏字段值和来自请求的 cookie 值,如果两者都匹配,那么你就可以开始了......

于 2013-03-26T09:00:59.353 回答
0

您无法真正保护匿名表单免受 CSRF 攻击。仅仅因为其他站点可以充当普通用户。我可以创建一个curl向匿名表单发出请求的站点,并将 cookie 和令牌存储在变量中。然后再次请求发布表单。该脚本并不是真正伪造请求,而是自动发布。

CSRF 的目的是防止脚本/人代表另一个用户执行操作。所以那将是我试图以你的身份发帖。为了防止带有令牌的会话/cookie 方法是一个很好的解决方案。因为我没有办法得到你的会话和令牌,除非你的网站在其他方面有缺陷。我建议阅读OWASP 指南,以了解您应该注意什么。

您应该始终做的另一件事是确保“操作”始终符合POST请求,因此我不能简单地在您的论坛上放置链接到“ http://www.yoursite.com/delete.php?id=10 ”的图片。如果您允许GET请求并打开包含此图像的页面,我会伪造请求。如果你只允许POST它不会有任何结果。

于 2013-03-26T08:55:53.177 回答