频道栏目
首页 > 安全 > 网站安全 > 正文

从Github被 Hack,谈Rails的安全性( Mass-assignment )

2012-03-08 11:04:27      个评论      
收藏   我要投稿
关于 Github 被入侵这件事,目前在国外开发圈传的沸沸扬扬。看来中文圈还没有消息,我来报导一下到底发生了什麽事好了。顺便宣导一下开发 Rails 程式码需要注意的其中一个观念..

 

到底发生了什麽事

Rails 的 master 被某个 hacker 塞上这一段 commit。以证明 Github 是可以被入侵的。

为什麽会发生这件事(纠纷起源)

有个俄罗斯 Hacker : homakov 到 Rails 的 Github issue 页,report 了一个 issue

声称他发现很多「中等程度以下的」Rails 开发者开发任何网站,都没有在 model 内作上任何 attr_accessible 的防护,这样会引起很多安全性的问题。

Rails 官方应该设计一个机制强迫大家一定得「使用」attr_accessible

因为写 code 要塞 attr_accessible 被多数开发者认为是根本是一个「常识」。所以这个 issue 很快就被 Rails core team 关掉了。他的意见是这不是 Rails 的问题,而是开发者的问题。(正常人都会做出这样的反应)

这个 Hacker 觉得他好心来报告,但是却被忽视,感到很生气。

于是!他 Hack 了 Github 证明这件事情是真的。

他不仅利用这个漏洞在 rails/rails 中塞了 commit ,连当初被关掉的 issue ,也用同样方法打开了。

所以这下就闹到举世震惊了!…XDDDDD

为什麽会发生这件事(剖析 Rails )

从 Rails 表单机制谈起

Rails 秉持着 Don’t Repeat Yourself 的精神,将 Form 表单 Helper 直接与 Model 栏位直接结合,节省不少开发者撰写表单的时间,是一个很聪明的作法。

<%= form_for @post do |f| %> <%= f.text_field :title %> <%= f.text_area :content %>  <%= f.sumbit "Submit" %> <% end %> 当表单送出后,会被压缩成一个 params[:post] 这样的 Hash。controller 裡面透过 massive-assignment 的技巧直接 mapping 进 Model 裡。

class PostController < ApplicationController  def create  @post = current_user.posts.build(params[:post])  if @post.save  # do something  else  # do another thing  end  end end 这是一个自 Rails 诞生以来就有的机制了,十分便手。

有些不了解的 Rails 的其他 Developer 批评这是一个不安全设计,并因此拒绝使用 Rails。栏位暴露在外被人知道,让他们感到非常不自在。

万一被人猜到 user 权限是用 user.is_admin 作为 boolean 值,这样岂不是很危险吗?在修改个人资讯页时,假造 DOM 就不是可以把自己提升为 admin 了吗?

Rails 内建的安全防御措施

Rails 也不是没有针对这件事设计出防御措施,有两组 model API :attr_accessibleattr_protected。其实也就是 白名单、黑名单设计。

attr_accessible 加在 model 裡,可以挡掉所有 massive assignement 传进来的值,只开放你想让使用填写的栏位。

class Post < ActiveRecord::Base  attr_accessible :title, :content end

attr_protected 是完全相反地机制。

知名认证 Plugin 皆内建 attr_accessible

也因为 user.is_admin 几乎是所有懒惰开发者会写出来的 code。因此长久的历史演变下来,许多知名认证 plugin,如 devise ,restful-authentication 等等…,在 User model 裡都会加上 attr_accessible(你可能没有察觉到,因为可能是透过 include Module 塞进来的功能)。

因为是隐藏的内建防御,很多不够经验的开发者,反而会被这道自动防御整到,在设计修改使用者资讯这个功能时,常常表单明明没问题,但就是修改不了除了密码和 email 以外的栏位 XDDD

User model 自动防御,那其他 model 呢?

好问题!这就是这次 Github 发生的问题。严格来说,根本不是 rails/rails 的错,而是 Github 内某个被骂 mid/junior level 的 developer 的错。他根本没有对其他 model 作上保护,才被 hacker 有机可趁。

Hacker 也是想要证明连 Github 都会犯这种错,才会闹出这种事件

看到 Github 的事件,我该做什麽?

请回家读这两组 model API :attr_accessibleattr_protected 的作用。

并检查你的 project 内是否有类似问题:一般来说,容易被攻击的点都跟 relation 比较有关係。也就是 xxxxx_id 的部分都要清查。

Scoped Mass Assignment

这是 Rails 3.1 加入的新 feature : scoped mass assignment, http://enlightsolutions.com/articles/whats-new-in-edge-scoped-mass-assignment-in-rails-3-1

我也建议你阅读

Rails core team 目前的解法

大师 Yahuda Katz (wycats) 目前起草了一份新的 proposal,并且丢在 Hacker News 让乡民讨论。应该可能近期就会近 Rails core 或以 plugin 的方式释出。

我个人的感想

其实昨晚睡前看到一堆人说 Github 被 Hacked 掉,然后追了几篇讨论串之后,觉得真的是没什麽,因为就我来说,的确应该就是这个 hacker 觉得有必要提醒大家,但这对多数的 Rails Developer 来说,根本是超小的小事,不值得这麽大惊小怪。

结果愤怒的 Hacker 攻击了 Github,Github 真的还因为某个 developer 犯了低级错误中招。但我还是觉得没什麽…

XSS V.S. Massive Assignment

后来睡醒以后才发现不对,其实这东西应该要被拿来跟 auto escape 相比:XSS 是一般设计 Web Application 最容易中招的攻击。

XSS 的原因肇因是让开发者开放让使用者自行输入内容,然后无保护的读出来,Hacker 会利用这种漏洞,写进有害的 JavaScript 让使用者中招。正确的方式应该是:内容读出来之后,都要利用 html_escape 滤掉。

问题是,html_escape 滤不胜滤,没有开发者能够那麽神,写任何一段 code 都会自律的加上 h(content)。最后 Rails core 痛定思痛,在 Rails 3.0 后效法 Django 的设计,在读出 content 时,一律先 escape。除非有必要,才另行设定不需 escape。

我想这次的 massive assignment 问题应该也要比照办理才对…

延伸阅读:

国外乡民懒人包:GitHub and Rails: You have let us all down.

DHH 给出的 37Signals 的作法:https://gist.github.com/1975644

相关TAG标签 安全性
上一篇:xss代码:asp截取cookie发送到邮箱
下一篇:跨站语句大全
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站