将反 CSRF 令牌存储在 cookie 中

信息安全 Web应用程序 csrf
2021-09-07 07:22:13

我为每个会话生成一个随机的反 CSRF 令牌并将其存储在 cookie 中(http_only设置了标志)。然后我将该标记添加到表单(在隐藏的输入字段中)和链接中。

在服务器上接收请求时,我检查表单或链接的cookie和anti-CSRF token字段是否存在,并且这两个值相同;如果不是,则认为是 CSRF 攻击,请求会被拒绝并带有适当的消息。

这种机制至少是安全/足够的吗?(也就是说,在浏览器没有安全漏洞的情况下。)

我认为攻击者无法读取或设置他不拥有的域的 cookie,因此他无法伪造具有相同令牌的请求。

4个回答

您说“会话”-您有服务器端会话吗?如果是这样,为什么不将 CSRF 令牌放在会话中而不是客户端 cookie 中呢?这是正常的模式;它可以防止攻击者在他们有 cookie 固定的情况下使用他们自己生成的 CSRF 令牌值来对付另一个用户。

如果您没有服务器端存储,另一种类似的不需要额外 cookie 的防水方法是创建一个包含用户或会话 ID 的值,并使用带有服务器端机密的 MAC(通常是 HMAC)对其进行签名。然后,服务器可以验证表单中的令牌是否来自会话所在的用户。

攻击者无法读取或设置他不拥有的域的 cookie

嗯,可能……通常。cookie 注入往往会发生的方式(除了 XSS,在这种情况下你已经失去了更糟糕的情况):

  • 浏览器错误、过时的“通用域”表/规则等
  • 易受攻击的邻居域(例如,从 test.example.com 在 www.example.com 上设置 cookie)
  • 允许从攻击者域提供您的站点(始终检查主机名:是公认的良好域名)

这些通常是边缘问题,但它们取决于您作为应用程序作者可能无法控制的因素。因此,对于安全敏感的系统,最好不要依赖无法修复的 cookie。

纯粹作为一种对我来说听起来合理的反 CSRF 机制。标准保护是在隐藏的表单字段中使用随机令牌,然后在提交时检查它,所以在我看来,您的方案中唯一的区别是,您不是在服务器端持有该令牌,而是将其与cookie 中的令牌。您提出的解决方案听起来很像OWASP Anti-CSRF Cheatsheet中的“双重提交 cookie”选项

显然,如果您的应用程序中存在其他问题(例如跨站点脚本),您可能会遇到问题,但是 XSS 会导致各种问题。

根据我的观点,这不是完全安全的实现,因为它只验证 cookie 和 post 参数的值“相同且存在”,如果应用程序中存在CRLF 注入漏洞(即 HTTP 响应拆分)让我设置另一个名为“csrftoken=test”的 cookie 和 csrf post 参数值到“test”并发送请求 - 这会绕过整个 csrf 检查,因为这两个值都是测试和匹配的。

如果我错了,请纠正我。

当您在受保护的应用程序中进行会话时,攻击者可以向您发送您的浏览器将打开的链接。即使在电子邮件中显示图像也可能发生这种情况。在这种情况下,来自浏览器的请求包含会话 cookie,但不包含反 CRSF 令牌,服务器可以使来自受害者浏览器的 malicius 请求无效。CSRF 标记必须存在于服务器会话和 html 页面中,而不是每次从客户端发送的 cookie 中。还建议在每次请求时重新生成值(一次令牌)并再次询问登录凭据以获取特殊请求(更改密码,应用电子邮件过滤器 ecc)。