在 CSRF 上
首先,必须弄清楚 CSRF 到底是什么。
跨站请求伪造 是一种对网站的恶意利用,通过该攻击从网站信任的用户传输未经授权的命令。
考虑以下示例:黑客知道您在 www.example.com 上有一个帐户,假设您已登录该网站,并且仍在运行有效会话。现在,黑客可以引诱您打开另一个网站,例如 trustme.com,他在该网站上发布了带有以下代码的图像:
<img src="http://www.example.com/users/delete"/>
如果 www.example.com 的程序员实际上可以通过简单的 GET 请求通过该 URL 删除您的帐户,并且黑客知道,只需使用您的有效 cookie 查看和加载该图像就会删除您在 example.com 上的帐户,即使您只是浏览 trustme.com,而且这两个网站似乎彼此无关。
总结这个例子,CSRF 利用了站点在用户浏览器中的信任,在本例中是 www.example.com 在您的浏览器中的信任。
对您的案例使用该类比意味着利用您的站点对用户浏览器的信任 - 但该信任尚未建立,因为用户在看到您的表单时尚未登录。但是,您必须确保用户在已经登录并尝试再次使用该表单加载页面时被重定向,否则可以利用建立的信任。
因此,根据经验,每当您使用 cookie 和会话请求验证用户时,即确认或建立对用户的信任时,请使用 CSRF 保护。由于您希望在用户注册时建立对他的信任,因此同样适用。
不幸的是,CSRF 攻击不仅限于此。我发现了另外两件可能发生的事情(当然不限于此):
1.:以下是监视您的帐户的一个很好的例子,通过省略登录表单上的 CSRF 保护来实现:
- 黑客在您真正信任的网站 (youtrustthis.com) 上创建了一个帐户
- 他使用自己的凭据从您的浏览器伪造登录请求,并诱骗您使用他的帐户
- 如果您没有注意到您实际上是在以其他用户身份浏览 youtrustthis.com,那么攻击者稍后会看到您“代表他”所做的事情,这几乎是在监视您
2.:如果没有 CSRF 保护,黑客可以在他自己的 html 文档中模仿您的登录或注册表格,并方便地一次又一次地提交(或者只是使用终端上的curl进行),而受信任的站点不会注意到请求没有实际上来自其本身——即,受信任域上的实际登录表单从未显示在您的浏览器中,也没有从那里提交。这使他能够更轻松地执行蛮力攻击。如果恶意用户成功地尝试找出凭据,您的服务器将响应一个有效的会话 cookie 并信任该用户,从而窃取您的身份。如果是注册表单,他将能够注册大量帐户,从而向您的数据库发送垃圾邮件。
总结一下:使用 CSRF 保护。恶意用户可以非常多地使用不安全的登录和注册表单来滥用您的网站并监视您的用户或窃取他们的身份。
有关更多信息,另请参阅此类似问题(用于登录表单)和此学术论文。后者在第 3 页有关于登录 CSRF 的专门章节。另外,请查看此CSRF 预防备忘单。
关于潜在的解决方法
由于 CSRF 保护使用会话来比较在服务器端生成的令牌与从表单提交的令牌,我想不出一种仅在客户端执行此操作的方法,即不触及 Rails 堆栈。关键是客户端仅在生成服务器端后才收到令牌。