注册表单上是不是需要 CSRF 保护?

Posted

技术标签:

【中文标题】注册表单上是不是需要 CSRF 保护?【英文标题】:Is CSRF Protection necessary on a sign-up form?注册表单上是否需要 CSRF 保护? 【发布时间】:2013-03-14 04:57:00 【问题描述】:

默认情况下,Rails 会自动为所有表单添加 CSRF 保护,方法是向站点生成的所有表单添加 authentication_token

我真的希望我的网站在网站的首页上有一个简单的注册表单,这当然是一个静态 html 页面。理想情况下,这将完全避免碰到 Rails 堆栈,从而使我可以向首页提供更多请求。

这样做的缺点是它使 CSRF 保护更加困难。

但我想知道是否真的有必要在注册表单上设置 CSRF 保护,因为 CSRF 攻击通常依赖于受害者登录,以便可以利用信任。如果验证正确,注册表单让用户登录,但我认为这对攻击者没有任何用处。

对此是否有既定观点或使用 Rails/jQuery 的解决方法?

【问题讨论】:

Do login forms need tokens against CSRF attacks?的可能重复 Sigh 这不是重复的。请阅读另一个问题,它是关于登录表格的。这是关于注册阶段。 请注意,如果您的注册表单在提交后自动让您登录,那么它很容易受到与登录页面***.com/questions/6412813/…相同类别的CSRF攻击 【参考方案1】:

不,对于这种特定情况不是。 CSRF 攻击允许攻击者利用受害者拥有的权利, 例如bank.com/pay?ammount=1000&to=34.67.978.246

攻击登录表单是没有意义的,因为如果攻击者拥有对登录字段进行成功攻击所需的信息(用户名和密码),则攻击者可以自行登录。

Rails 对登录字段使用 CSRF 保护的原因很简单:在全局范围内实现 CSRF 保护要比对 95% 的字段简单得多;)

【讨论】:

不正确。谷歌“登录 CSRF”。攻击者可以让您登录或为您注册他们也有权访问的帐户。对该站点的任何继续使用都将在攻击者也有权访问的帐户上进行。另请参阅此问题:***.com/questions/6412813/… 在某些非常特殊的情况下,这可能是一种风险。攻击者必须提供一个看起来与用户帐户完全相似的有效帐户。如果您计划进行这种复杂的攻击,您还可以创建一个页面,使用 AJAX 获取 CSRF 密钥然后提交。 “您还可以创建一个页面,使用 AJAX 获取 CSRF 密钥然后提交它” - 不,这是 CSRF 保护实际上阻止的情况。这不仅仅是您提交时需要的令牌,它是一个必须对应于用户唯一的cookie的令牌,攻击者的站点由于同源策略而无法读取或写入。如果防止 CSRF,则无法使用 AJAX 获取 CSRF 密钥并从另一个站点提交。 令我沮丧的是,这仍然是公认的答案;据说 CSRF 保护对于注册表单是“不需要的”——这是不正确的。 CSRF 保护不仅可以防止代表已建立的用户帐户的未经授权的操作,而且(通常称为“登录 CSRF”)还可以防止攻击者在未经授权的情况下拦截用户的注册过程,从而诱骗用户在帐户下注册攻击者以用户的名义创建并继续访问,如果用户继续使用该帐户,将会产生长期的安全后果。【参考方案2】:

是的,所以其他网站无法模仿您的注册表单!就这么简单。

他们这样做能达到什么目的?

首先:你不想允许这样。您想拥有请求的来源。 第二:可以阻止虚假警报。 第三:如果你允许自动登录后注册它就像login form csrf一样容易受到攻击

【讨论】:

【参考方案3】:

一般来说,保护您的注册表单免受 CSRF 攻击是一个好主意。 考虑 Google 搜索,并假设登录表单受到 CSRF 保护,但注册表单易受攻击。攻击者可以强迫受害者使用攻击者知道的凭据注册一个新帐户,从那一刻起,受害者所做的任何搜索也将对攻击者可见,因为他知道登录受害者帐户的凭据。 这假设易受攻击的网站在用户注册后立即登录。

电子邮件提供商的其他情况是创建用于垃圾邮件目的的帐户。攻击者可以强制受害者创建新帐户,并在注册表中使用 CSRF,并使用这些帐户发送垃圾邮件。这个想法是为了打败基于 IP 或国家/地区限制帐户创建的安全机制。

但是,在特定情况下,可能无法利用易受攻击的注册表单,但这种分析对于非该主题的专家来说可能很难。保护表单是个好主意,但是可以创建成功攻击的场景并不多,因此风险通常很低。

【讨论】:

【参考方案4】:

在我看来,从注册表单中关注 csrf 的技术理由很少。攻击者可以欺骗某人在您的网站上创建一个新帐户 - 如果受害者随后使用您的网站,攻击者可以监视他们的行为,因为他也可以访问该帐户?

更有可能的风险可能是非技术性的。当您的站点获得安全审核时,您必须解释为什么 csrf 在这里没有风险......并且很难证明否定...... “Appscan 已将此标记为一个严重的安全漏洞 - 你为什么不修复它?为什么你不能像 Charles 一样有一个干净的报告?” :)

【讨论】:

【参考方案5】:

如果您想缓存首页但仍具有 CSRF 保护(这可能是一个好主意,正如 Charles 所说),您可以在页面加载后通过 javascript 注入适当的真实性令牌。

在“CSRF 和 form_authenticty_token”标题下的 http://broadcastingadam.com/2011/05/advanced_caching_in_rails/ 有一些关于此的信息。相关代码为:

$("meta[name='csrf-token']").attr('content', '<% Rack::Utils.escape_html(request_forgery_protection_token) %>');
$("meta[name='csrf-param']").attr('content', '<% Rack::Utils.escape_html(form_authenticity_token) %>');

使用这种技术,您可以缓存整个主页,但代价是所有客户端发出额外(但非常小且快速)的请求来获取此身份验证令牌。

【讨论】:

这确实可行,尽管您肯定会失去通过缓存获得的负载减少。现在,您不再使用令牌动态呈现页面,而是将其替换为对缓存的静态页面的一次调用以及对包含传递给 Javascript 的令牌的动态呈现页面的调用。【参考方案6】:

在 CSRF 上

首先,必须弄清楚 CSRF 到底是什么。

Cross site request forgery 是一种对网站的恶意利用,利用该网站信任的用户传输未经授权的命令。

考虑以下示例:黑客知道您在 www.example.com 上拥有一个帐户,假设您已登录该网站并且仍在运行有效会话。现在,黑客可以引诱您打开另一个网站,例如 trustme.com,他在该网站上发布了一张带有以下代码的图片:

<img src="http://www.example.com/users/delete"/>

如果 www.example.com 的程序员实际上可以通过简单的 GET 请求通过该 URL 删除您的帐户,并且黑客知道这一点,只需使用您的有效 cookie 查看和加载该图像就会删除您的帐户示例.com,即使您只是浏览 trustme.com,而且这两个网站似乎彼此没有任何关系。

总结这个例子,CSRF 利用了网站在用户浏览器中的信任,在本例中是 www.example.com 在您的浏览器中的信任。

在您的案例中使用该类比意味着利用您的网站对用户浏览器的信任 - 但该信任尚未建立,因为用户在看到您的表单时尚未登录。 不过,您必须确保用户在已登录并尝试再次使用该表单加载页面时被重定向,否则可能会利用已建立的信任。

因此,根据经验,每当您使用 cookie 和会话请求验证用户时,即确认或建立对用户的信任时,请使用 CSRF 保护。由于您希望在用户注册时建立对他的信任,因此同样适用。

不幸的是,CSRF 攻击不仅限于此。我发现了另外两件可能发生的事情(当然不限于此):

1.:以下是监视您的帐户的一个很好的例子,通过省略登录表单上的 CSRF 保护来实现:

    黑客在您真正信任的网站 (youtrustthis.com) 上创建了一个帐户 他使用自己的凭据从您的浏览器伪造登录请求,并诱骗您使用他的帐户 如果您没有注意到您实际上是以其他用户的身份浏览 youtrustthis.com,攻击者稍后会看到您“代表他”所做的事情,这几乎是在监视您

2.: 如果没有 CSRF 保护,黑客可以在他自己的 html 文档中模仿您的登录或注册表单,并方便地一次又一次地提交(或者只是在终端使用curl 进行)而不受信任的站点注意到请求实际上并非来自自身 - 即,受信任域上的实际登录表单从未显示在您的浏览器中,也没有从那里提交。这使他能够更轻松地执行蛮力攻击。如果恶意用户成功地尝试找出凭据,您的服务器将使用有效的会话 cookie 进行响应并信任该用户,从而窃取您的身份。如果是注册表单,他将能够注册大量帐户,从而向您的数据库发送垃圾邮件。

总结一下:使用 CSRF 保护。恶意用户可以非常多地使用不安全的登录和注册表单来滥用您的网站并监视您的用户或窃取他们的身份。

有关详细信息,另请参阅this similar question (for login forms) 和this academic paper。后者在第 3 页有一个关于登录 CSRF 的专门章节。另外,请查看此CSRF prevention cheat sheet。

关于潜在的解决方法

由于 CSRF 保护使用会话来比较在服务器端生成的令牌与从表单提交的令牌,我想不出一种仅在客户端执行此操作的方法,即不触及 Rails 堆栈。关键是客户端只有在服务器端生成令牌后才会收到令牌。

【讨论】:

谢谢。这是一个全面的答案,但我专门谈论的是注册表格,而不是登录表格。我了解登录表单必须是 CSRF 证明。但是,如果有人使用假网站/curl 等创建帐户对我来说并不重要,那么不保护注册表单是否存在问题?因为肯定不能以这种方式危害其他用户? 一般来说答案是:任何形式都应该受到 CSRF 保护。考虑到最小的开销 csrf 保护原因,我真的会使用它。注册后,无论如何都必须加载 rails 堆栈。这是你的决定,但我会同意的。 感谢您的回答,它让我明白了很多,但我不得不不同意您的最后一点。在我的投资组合中,不缓存首页会产生巨大的开销。首页只是获得网站任何其他部分获得的流量的倍数,并且最有可能遇到流量高峰。所以对我们来说,如果在注册表单上没有解决 csrf 的问题,它就不能出现在首页上。 我将采取相反的立场并说这完全没问题。查尔斯的评论闻起来像是“我不想考虑你的案子,所以我会给出一个全面的回应”。 不保护您的注册表单可能允许攻击者为您创建一个帐户,如果您继续使用该帐户,攻击者将可以访问同一帐户。您可以通过让您的注册表单不让您登录并强制用户在首次登录时更改密码来帮助缓解这种情况,确保登录表单具有 CSRF 保护。您的用户可以更轻松地保护注册表单。还有一些不需要令牌的替代方法,例如引用者或来源检查:owasp.org/index.php/…

以上是关于注册表单上是不是需要 CSRF 保护?的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用我网站中特定页面的 csrf 保护?

AngularJS SpringBoot 没有认证 csrf 保护

在 ajax 提交时禁用 symfony 2 csrf 令牌保护

Flask 中 AJAX 身份验证的 CSRF 保护

SPA 使用的经过身份验证的 Rest API:如何获取用于登录和注册表单的 CSRF 令牌?

使用 CSRF 表单令牌是不是有助于防止垃圾邮件?