使用会话令牌或随机数进行跨站点请求伪造保护 (CSRF)?

Posted

技术标签:

【中文标题】使用会话令牌或随机数进行跨站点请求伪造保护 (CSRF)?【英文标题】:Using a session token or nonce for Cross-site Request Forgery Protection (CSRF)? 【发布时间】:2011-10-19 04:44:07 【问题描述】:

我继承了一些最近受到攻击的代码,其中攻击者发送了重复的远程表单提交。

我使用我为每个用户创建的会话身份验证令牌(不是会话 ID)实施了预防措施。虽然我意识到这个特定的攻击不是 CSRF,但我从这些帖子中调整了我的解决方案(尽管过时了)。

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29 http://tyleregeto.com/a-guide-to-nonce http://shiflett.org/articles/cross-site-request-forgeries

但是,它仍然觉得这里存在一些漏洞。虽然我知道没有什么是 100% 安全的,但我有一些问题:

难道潜在的攻击者不能简单地启动一个有效会话,然后在他们的每个请求中包含会话 ID(通过 cookie)吗? 似乎 nonce 会比 session token 更好。生成和跟踪 nonce 的最佳方式是什么? 我遇到了一些关于这些解决方案只是单一窗口的观点。有人可以详细说明这一点吗? 这些解决方案是否总是需要会话?还是可以在没有会话的情况下创建这些令牌? 更新,这个特定页面只是一个单页表单(无需登录)。因此,仅仅为了生成令牌而启动会话似乎有些过分。 我是否可以实施更简单的解决方案(不是 CAPTCHA)来防止这种不使用会话的特定攻击。

最后,我正在寻求更好的理解,以便实施更强大的解决方案。

【问题讨论】:

您能否提供一些在您的网站上进行的确切攻击模式?您对帖子的最新更新使您不太可能遭受简单的 CSRF 攻击——它们通常利用会话漏洞(它们甚至在 wiki 上被称为“会话骑行”)。看起来您的表单问题可以通过验证码轻松解决。 这是一种自动攻击,他们发送远程表单提交。验证码可能阻止了此类攻击。但是,我仍然对以更强大的方式保护表单感兴趣。理想情况下,不要使用验证码恶化用户体验。因此是会话令牌或随机数。 呃,这正是机器人所做的——它们会自动提交一些表单——这不是 CSRF 攻击。如果您发明了一些不涉及反向图灵测试的针对机器人的保护措施,您可能会在互联网上掀起一场革命:)祝您好运! 公平。如前所述,我仍然对会话令牌/随机数感兴趣,因为它们与 CSRF 保护有关。虽然我很欣赏讽刺,但您的 cmets 并不是很有帮助。 好吧,你问了一个关于 CSRF 攻击的问题,结果你甚至没有会话(这种类型的攻击依赖的主要内容)。我认为您应该删除这个问题并创建一个新问题,因为这根本没有意义。我认为这就是另一个人删除他的答案的原因。您应该阅读en.wikipedia.org/wiki/Cross-site_request_forgery 了解这种攻击的真正含义。 【参考方案1】:

据我了解,您需要做三件事:使所有更改数据操作仅适用于 POST 请求,禁止没有有效推荐人的 POST 请求(它必须来自同一个域)并检查每个中的身份验证令牌POST 请求(POST 令牌值必须与 cookie 中的令牌相同)。

前两个将使执行任何有害的 CSRF 请求变得非常困难,因为它们通常是电子邮件、其他站点等中的隐藏图像,并且使用有效的引用者进行跨域 POST 请求在现代应该是不可能/很难做到的浏览器。如果不窃取用户的 cookie/嗅探他的流量,这将完全不可能进行任何有害的操作。

现在关于您的问题:

    这个问题真的让我很困惑:如果您正确使用身份验证令牌,那么攻击者必须从 cookie 中知道用户的令牌才能将其与请求一起发送,那么为什么启动一个有效的攻击者自己的会话会造成任何伤害? Nonce 将使您的所有链接变得丑陋 - 我从未见过有人再使用它们。而且我认为您的网站可以使用它,因为您必须保存/搜索数据库中的所有声明 - 生成声明的大量请求可能会非常快地增加您的数据库大小(并且搜索它们会很慢)。 如果您只允许每个 user_id 一个 nounce 以防止 (2) Dos 攻击,那么如果用户打开一个页面,然后打开另一个页面,然后提交第一页 - 他的请求将被拒绝,因为生成了新的 nounce 而旧的一个已经无效。 您将如何识别没有会话 ID 的唯一用户,无论是 cookie、GET 还是 POST 变量?

UPD:因为我们不再谈论 CSRF:您可能会实施许多晦涩难懂的防御措施来阻止蜘蛛机器人提交您的表单:

    不应该填写的隐藏表单域(机器人通常会填写他们看到的大部分名称好听的表单域,即使它们对用户来说确实是隐藏的) javascript 鼠标跟踪器(您可以分析记录的鼠标移动以检测机器人) 文件请求日志分析(页面加载时javascript/css/images在大多数情况下也应该加载,但一些(很少)用户将其关闭) Javascript 表单更改(当使用服务器端所需的 javascript 将隐藏(或不)字段添加到表单时:机器人通常不执行 javascript) Snort 等流量分析工具可检测 Bot 模式(奇怪的用户代理、太快的表单提交等)。

还有更多,但归根结底,一些现代机器人使用真实用户行为的完全模拟(使用真实的浏览器 API 调用) - 所以如果有人真的想要攻击你的网站,没有防御像这样会帮助你。即使是今天的 CAPTCHA 也不是很可靠——除了复杂的图像识别算法之外,您现在可以以低至 1 美元的价格为任何网站购买 1000 个由人工解决的 CAPTCHA(您可以在发展中国家找到这样的服务)。所以说真的,没有 100% 防御机器人 - 每种情况都不同:有时您必须自己创建复杂的防御系统,有时只需稍加调整就会有所帮助。

【讨论】:

+1 关于真正的 nonce 实现的开销的要点。 鉴于您的坚持,我已将此标记为答案。尽管如此,我确实发布了另一个问题。 好吧,你不应该接受这个答案 - 我要求寻求关闭。像这样的问题确实使查找有关 SO 的相关信息变得困难。但是在这个话题上——我想你会发现人们会像我一样回答这个问题(新话题中的当前答案重复我的答案)。 您的回答很有帮助,我使用了您提供的信息。因此,我将其标记为这样,并想象其他人会发现它有用。

以上是关于使用会话令牌或随机数进行跨站点请求伪造保护 (CSRF)?的主要内容,如果未能解决你的问题,请参考以下文章

CSRF 保护

Laravel CSRF 保护

跨站点请求伪造

Django网络安全跨站点请求伪造保护,CSRF如何正确使用

HTTP层 —— CSRF保护

通过“Referer”标头防止跨站点请求伪造