原文在:http://fxck.it/post/49101760571/rails
背景:用户的电脑并未被植入任何木马,但当出了用户电脑的网卡后,面临着一个不安全的网络世界。下面提到的某些技术的基础知识就不涉及了,只涉及跟 Rails 相关的。
如果你是通过 HTTP 来访问一个已经登陆了的网站,那么只能说,这种方式的访问的安全性是永远无法保障的。随便一个人截取了你的 cookie 就可以冒充你登陆该网站。
CookieStore。
今天看资料的时候看到 ActionDispatch::Session::CookieStore 这个东西,它会把 session 存储中的相关信息存在用户的浏览器端然后加个指纹上去。而与加密有关的 secret 保存在 config/initializers/secret_token.rb 这个文件中。
这么说来,这个 secret_token.rb 肯定就不能给其他人看到咯,否则就存在被攻击者伪造任意 session 的可能。在部署开源的 Rails 相关项目时,除了 database.yml 这个文件需要隐藏外,有必要时,也需要隐藏 secret_token.rb 这个文件。
Rails 出箱(out of box)即附带了 session 的功能,所以不用进行任何设置就可以对针对某一用户的 session 进行操作。识别用户是通过 session_id 来的,session_id 可以认为是不可破解或猜测的,只能嗅探得到。
--
我还原了一下 ruby-china 在我浏览器上设置的 session(抹掉了信息,只保留了格式)
{"session_id"=>"06fd9f57exxxxxxxxxxxxxxxxxxxx0dd", "_csrf_token"=>"eddCzjiFBIeGrrxxWxxxxxxxxxxxxxxxxxxxxps+Hxc=", "warden.user.user.key"=>["User", [1848], "$2a$10xxxxxxxxxxxxxxxKDX.YIpO"]} 首先 session_id 这关的伪造肯定过不了。
_csrf_token 貌似在我们的话题中不是很必要。
warden.user.user.key 虽然表露出:我在 User 表中,且 id 是 1848(我是 ruby-china 的 1848 号会员),但是 warden 在后面加了个 digest,所以也无法伪造。这个 digest 应该是存在于 User 表中的某个字段里。
--
很多时候,如果我们并没有 devise 或者 warden 这样的库的时候,我们会简单地保存 user_id 这个值在 session 中(用的时候,会在服务端取出 session[:user_id] 来得到 current_user)。在这样的情况下,如果不小心暴露了自己的 config/initializers/secret_token.rb 文件,那么,攻击者就可以简单地把 user_id 修改为其他用户的,并通过适当的算法得到 CookieStore 生成的那个 digest,然后 do evil。
这点需要好好注意。
--
以上提到的『适当的算法』在此:https://github.com/joernchen/evil_stuff/blob/master/ruby/sign-cookie.rb
ruby-china 的 secret_token.rb 在此:https://github.com/ruby-china/ruby-china/blob/master/config/initializers/secret_token.rb
--
这么说来,独立开发者的 Web 开发学习成本真的很高啊....不仅前端后端,还要注意各种安全性问题。
在 Rails 中,默认的 CSRF 机制貌似已经挡掉这个攻击方式了。
CSRF 虽然是个危害不小的技术,但是当网站在应用了某个 CSRF 的中间件时(Rails provide it out of box),就已经能成功阻挡这类攻击了。除非....
...除非玩 XSS。其实 CSRF 跟 XSS 这两类攻击还是分得蛮开的,记得 cnodejs 有一次被大家玩 XSS 玩疯了,我当时也中了招。如果你的网站可以被人插入 JS 代码进行 XSS 攻击的话,HTTPS 和 CSRF 之类的东西就都无法保住用户的安全了,用户只能被随意宰割。
关于 Rails 的安全性,这篇 guides 还挺好看的:
http://guides.rubyonrails.org/security.html
XSS 和 CSRF 的话,也推荐两篇我收藏的文章: