8. YAML 反序列化
就如大多数ruby开发人员在一月所学到的,使用YAML反序列化不信任的数据会带来安全隐患。网上已经有很多关于使用YAML的攻击的文章,所以我不会
在这里阐述了,但是总的来说,如果攻击者可以入侵YAML,它们就可以随意的在服务器上运行代码。我们的应用无需做任何事情,只需有序的载入YAML,就
会变得脆弱不堪。
虽然rails已经打了补丁,来避免转换的YAML通过HTTP请求发送到服务器。但是仍使用YAML作为#serialize功能和#store功能的默认的序列化格式,以下是存在风险的代码:
1 | class User < ActiveRecord::Base |
5 | store :theme , accessors: [ :color , :bgcolor ] |
大多数rails开发人员不会喜欢把随意的ruby代码保存在数据库,并且在读取记录后来解释运行它们,但是,这其实就等价于使用YAML反序列化的后
果。当存储的数据不包含随意的ruby对象的时候,它就违反了最小特权原则。这个允许在数据库里面保存数据的漏洞,最终会导致整个服务器被攻击者控制。
尤其当自认为YAML看起来起来安全时,实际上很危险。YAML格式是在远程代码执行漏洞爆发前,由数百名熟练的开发者所确定的。然而如今他是Ruby社区的重点之一,Rails的新开发者显然不会再经历YAML远程攻击之祸。
最佳实践:使用JSOM序列化格式而不是YAML序列化
1 | class User < ActiveRecord::Base |
2 | serialize :preferences , JSON |
3 | store :theme , accessors: [ :color , :bgcolor ], coder: JSON |
修复:Rails应该改变默认序列化格式,从YAML转到JSON。YAML应该作为Gem中的一个选择。 9. 批量赋值
Rails
4改用strong_parameters方式来处理批量赋值的漏洞,代替attr_accessible。params对象现在是
ActionController::Parameters的实例。strong_parameters工作的方式是检查那个Parameters实例为
“允许的”——开发者指定了哪个键(及类型)是可接受的。
总之这是一个积极的变化,却引入了attr_accessible体系中没有的新攻击方式。看下面的代码:
1 | params = { user: { admin: true }.to_json } |
4 | @user = User. new ( JSON .parse(params[ :user ])) |
JSON.parse返回一个常规的Ruby
Hash,而不是ActionController::Parameters的实例。用了strong_parameters,默认行为是允许Hash实
例通过批量赋值来设置任何属性。同样的问题发生在sinatra,在Sinatra程序中通过params访问ActiveRecord模型时——
Sinatra不会把这个Hash包装为ActionController::Parameters实例。 最佳实践: 当使用ActiveRecord模型和其它web框架时(或从缓存、队列中反序列化数据时),尽可能使用Rails自带的解析。将输入数据包装到ActionController::Parameters,这样strong_parameters可以生效。
修复方式: 还不明确什么是最好的处理方式。Rails可以重写反序列化方法,比如JSON.parse,返回ActionController::Parameters实例,但这相对有侵入性且可能导致兼容问题。
相关的开发者可以在敏感区域(比如User#admin)结合采用strong_parameters和attr_accessible来得到额外的保护,但对于多数情况可能矫枉过正。这只是一个需要心中有数的问题,期待能尽快解决。
感谢Brendon Murphy,使我意识到这个问题。
感谢Adam Baldwin、Justin Collins、Neil Matatell、Noah Davis和Aaron Patterson对本文的审阅。 |