什么是Rails中的真实性令牌?
当前回答
可以阻止的最小攻击示例:CSRF
在我的网站上邪恶。我说服你提交以下表格:
<form action="http://bank.com/transfer" method="post">
<p><input type="hidden" name="to" value="ciro"></p>
<p><input type="hidden" name="ammount" value="100"></p>
<p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>
如果您通过会话cookie登录到您的银行,那么cookie将被发送,并且在您甚至不知道的情况下进行转账。
也就是说,CSRF令牌开始发挥作用:
使用返回表单的GET响应,Rails发送一个非常长的随机隐藏参数 当浏览器发出POST请求时,它会发送参数,服务器只接受匹配的参数
因此,在一个真实的浏览器上的表单看起来是这样的:
<form action="http://bank.com/transfer" method="post">
<p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
<p><input type="hidden" name="to" value="ciro"></p>
<p><input type="hidden" name="ammount" value="100"></p>
<p><button type="submit">Send 100$ to Ciro.</button></p>
</form>
因此,我的攻击会失败,因为它没有发送authenticity_token参数,而且我不可能猜到它,因为它是一个巨大的随机数。
这种预防技术称为同步器令牌模式。
同源策略
但是,如果攻击者使用JavaScript发出两个请求,一个读取令牌,另一个进行转账,该怎么办?
仅使用同步器标记模式不足以防止这种情况!
这就是同源政策来拯救的地方,正如我在https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569#72569上解释的那样
Rails如何发送令牌
涵盖:Rails: csrf_meta_tag如何工作?
基本上:
如果表单不是GET表单,像form_tag这样的HTML助手会为您添加一个隐藏字段 AJAX由jquery-ujs自动处理,它从csrf_meta_tags(在默认模板中)添加到头部的元元素中读取令牌,并将其添加到任何发出的请求中。 uJS还尝试在过期的缓存片段中更新表单中的令牌。
其他预防方法
check if certain headers is present e.g. X-Requested-With: What's the point of the X-Requested-With header? https://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application? check the value of the Origin header: https://security.stackexchange.com/questions/91165/why-is-the-synchronizer-token-pattern-preferred-over-the-origin-header-check-to re-authentication: ask user for password again. This should be done for every critical operation (bank login and money transfers, password changes in most websites), in case your site ever gets XSSed. The downside is that the user has to type the password multiple times, which is tiresome, and increases the chances of keylogging / shoulder surfing.
其他回答
真实性令牌用于防止跨站点请求伪造攻击(Cross-Site Request Forgery attack, CSRF)。要理解真实性令牌,首先必须理解CSRF攻击。
CSRF
假设你是bank.example的作者。您的网站上有一个表单,用于通过GET请求将资金转移到不同的帐户:
黑客只需向服务器发送一个HTTP请求GET /transfer?数量= $ 1000000 &account-to = 999999,对吧?
错了。黑客的攻击没用。服务器基本上会想?
嗯?这个想要转移的人是谁。肯定不是账户的主人。
服务器如何知道这一点?因为没有session_id cookie来验证请求者。
当你用用户名和密码登录时,服务器会在你的浏览器上设置一个session_id cookie。这样,您就不必用用户名和密码验证每个请求。当你的浏览器发送session_id cookie时,服务器知道:
哦,那是无名氏。他在两分半钟前成功登陆。他可以出发了。
黑客可能会想:
嗯。正常的HTTP请求不会起作用,但如果我能得到session_id cookie,我就很好了。
用户浏览器为银行设置了一堆cookie。域的例子。每次用户向银行提出请求时。例如域,所有的cookie都会被发送。包括session_id cookie。
因此,如果黑客能够让您发出get请求,将资金转移到他的帐户,他就成功了。他怎么能骗你这么做呢? 与跨站点请求伪造。
其实很简单。黑客可以让你访问他的网站。在他的网站上,他可以有以下图片标签:
<img src="http://bank.example/transfer?amount=$1000000&account-to=999999">
当用户的浏览器遇到图像标记时,它将向该url发出GET请求。由于请求来自他的浏览器,它将发送与bank.example相关的所有cookie。如果用户最近登录了银行。session_id cookie将被设置,服务器将认为用户打算转移$1,000,000到帐户999999!
嗯,只要不去危险的地方,你就会没事的。
这还不够。如果有人把这张照片发到Facebook上,出现在你的留声板上怎么办?如果它是通过XSS攻击注入到您正在访问的站点中呢?
没那么糟。只有GET请求是脆弱的。
不正确的。可以动态生成发送POST请求的表单。下面是来自Rails安全指南的例子:
<a href="http://www.harmless.example/" onclick="
var f = document.createElement('form');
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = 'http://www.example.com/account/destroy';
f.submit();
return false;">To the harmless survey</a>
真实性令牌
当你的ApplicationController有这个:
protect_from_forgery with: :exception
这样的:
<%= form_tag do %>
Form contents
<% end %>
编译成:
<form accept-charset="UTF-8" action="/" method="post">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
Form contents
</form>
具体来说,生成了以下内容:
<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
为了防止CSRF攻击,如果Rails没有看到随请求一起发送的真实性令牌,它就不会认为该请求是安全的。
攻击者如何知道这个令牌是什么?每次生成表单都会随机生成一个不同的值:
跨站点脚本(XSS)攻击——就是这样。但这是不同时期的不同弱点。
真实性令牌的设计使您知道您的表单是从您的网站提交的。它是由运行它的机器生成的,具有唯一的标识符,只有您的机器知道,因此有助于防止跨站请求伪造攻击。
如果您只是在rails拒绝AJAX脚本访问方面遇到困难,那么您可以使用
<%= form_authenticity_token %>
在创建表单时生成正确的令牌。
您可以在文档中阅读更多关于它的信息。
Beware the Authenticity Token mechanism can result in race conditions if you have multiple, concurrent requests from the same client. In this situation your server can generate multiple authenticity tokens when there should only be one, and the client receiving the earlier token in a form will fail on it's next request because the session cookie token has been overwritten. There is a write up on this problem and a not entirely trivial solution here: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/
可以阻止的最小攻击示例:CSRF
在我的网站上邪恶。我说服你提交以下表格:
<form action="http://bank.com/transfer" method="post">
<p><input type="hidden" name="to" value="ciro"></p>
<p><input type="hidden" name="ammount" value="100"></p>
<p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>
如果您通过会话cookie登录到您的银行,那么cookie将被发送,并且在您甚至不知道的情况下进行转账。
也就是说,CSRF令牌开始发挥作用:
使用返回表单的GET响应,Rails发送一个非常长的随机隐藏参数 当浏览器发出POST请求时,它会发送参数,服务器只接受匹配的参数
因此,在一个真实的浏览器上的表单看起来是这样的:
<form action="http://bank.com/transfer" method="post">
<p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
<p><input type="hidden" name="to" value="ciro"></p>
<p><input type="hidden" name="ammount" value="100"></p>
<p><button type="submit">Send 100$ to Ciro.</button></p>
</form>
因此,我的攻击会失败,因为它没有发送authenticity_token参数,而且我不可能猜到它,因为它是一个巨大的随机数。
这种预防技术称为同步器令牌模式。
同源策略
但是,如果攻击者使用JavaScript发出两个请求,一个读取令牌,另一个进行转账,该怎么办?
仅使用同步器标记模式不足以防止这种情况!
这就是同源政策来拯救的地方,正如我在https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569#72569上解释的那样
Rails如何发送令牌
涵盖:Rails: csrf_meta_tag如何工作?
基本上:
如果表单不是GET表单,像form_tag这样的HTML助手会为您添加一个隐藏字段 AJAX由jquery-ujs自动处理,它从csrf_meta_tags(在默认模板中)添加到头部的元元素中读取令牌,并将其添加到任何发出的请求中。 uJS还尝试在过期的缓存片段中更新表单中的令牌。
其他预防方法
check if certain headers is present e.g. X-Requested-With: What's the point of the X-Requested-With header? https://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application? check the value of the Origin header: https://security.stackexchange.com/questions/91165/why-is-the-synchronizer-token-pattern-preferred-over-the-origin-header-check-to re-authentication: ask user for password again. This should be done for every critical operation (bank login and money transfers, password changes in most websites), in case your site ever gets XSSed. The downside is that the user has to type the password multiple times, which is tiresome, and increases the chances of keylogging / shoulder surfing.
因为真实性令牌是如此重要,在Rails 3.0+你可以使用
<%= token_tag nil %>
创建
<input name="authenticity_token" type="hidden" value="token_value">
在任何地方
推荐文章
- 如何找到包含匹配值的哈希键
- 未初始化的常量ActiveSupport::Dependencies::Mutex (NameError)
- 如何在Rails中找到当前的路由?
- 在Ruby中->运算符叫什么?
- Rails参数解释?
- Ruby中DateTime和Time的区别
- 如何从代理服务器后面更新Ruby Gems (ISA-NTLM)
- 如何用另一个键替换哈希键
- 添加一个CSS类<%= f.submit %>
- attr_accessor和attr_accessible的区别
- 如何从Ruby文件路径中获得没有扩展名的文件名
- 创建新用户时出现ActiveModel::ForbiddenAttributesError
- rvm安装失败:“rvm不是一个函数”
- 覆盖设计注册控制器
- 学习Ruby on Rails