为什么对参数哈希进行切片会在批量分配时带来安全问题?
防止批量分配安全风险的官方方法是使用 attr_accessible 。然而,一些程序员认为这不是模型的工作(或者至少不仅仅是模型的工作)。在控制器中执行此操作的最简单方法是对 params 哈希进行切片:
@user = User.update_attributes(params[:user].slice(:name))
但是文档指出:
请注意,使用 Hash#except 或 Hash#slice 代替 attr_accessible 清理属性并不能提供足够的保护。
这是为什么? 为什么参数的白名单切片不能提供足够的保护?
更新: Rails 4.0 将提供强参数,这是对参数的精细切片,所以我猜整个切片的事毕竟没那么糟糕。
The official way of preventing security risks with mass-assignment is using attr_accessible. However, some programmers feel this is not a job for the model (or at least not only for the model). The simplest way of doing it in a controller is slicing the params hash:
@user = User.update_attributes(params[:user].slice(:name))
However the documentation states:
Note that using Hash#except or Hash#slice in place of attr_accessible
to sanitize attributes won’t provide sufficient protection.
Why is that? Why a whitelist-slicing of params does not provide enough protection?
UPDATE: Rails 4.0 will ship strong-parameters, a refined slicing of parameters, so I guess the whole slicing thing was not so bad after all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
控制器中的 slice 和 except 问题可能与模型中的
accept_nested_attributes_for
结合使用。如果您使用嵌套属性,则需要在所有位置对参数进行切片,然后在控制器中更新它们,这并不总是最简单的任务,尤其是在深度嵌套的情况下。使用attr_accesible
就不会出现这个问题。The problem with slice and except in controller might occur in combination with
accept_nested_attributes_for
in your model. If you use nested attributes, you would need to slice parameters on all places, where you update them in controller, which isn't always the easiest task, especially with deeply nested scenarios. With usingattr_accesible
you don't have this problem.从 Rails 4 开始,对参数进行切片将是处理批量分配安全性的首选方法。 Rails 核心团队现在已经开发了一个插件来处理这个问题,他们正在致力于集成对嵌套属性和签名表单的支持。绝对值得一看: http://weblog.rubyonrails.org/2012/ 3/21/强参数/
As of Rails 4, slicing the parameters will be the preferred method of dealing with mass assignment security. The Rails core team has already developed a plugin to deal with this now, and they are working on integrating support for nested attributes and signed forms. Definitely something to check out: http://weblog.rubyonrails.org/2012/3/21/strong-parameters/
DHH 关于控制器切片与单独白名单的有趣要点:
https://gist.github.com/1975644
评论强调在控制器内管理此内容的需要:
https://gist.github.com/1975644#gistcomment-88369
我个人将 attr_accessible 与 slice 一起应用,以确保没有意外的情况发生。切勿仅依赖黑名单!
Interesting gist from DHH on slicing in controller vs whitelisting alone:
https://gist.github.com/1975644
Comment reinforcing the need to manage this within the controller:
https://gist.github.com/1975644#gistcomment-88369
I personally apply both - attr_accessible with slice to ensure nothing unexpected gets through. Never rely on blacklisting alone!
只需从 params 哈希中删除 :name 即可防止为该操作设置该属性。它仅适用于您记得保护的操作。
但是,这种做法并不能保护您免受使用自动添加的所有关联方法的滥用。
即使您从 params 中删除了
comments
属性,也会让您容易受到设置comments_ids
属性的攻击。由于为关联添加了相当多的方法,并且它们将来可能会发生变化,因此最佳实践是使用
attr_accessible
保护模型上的属性。这将最有效地阻止此类攻击。Just removing the :name from the params hash works to prevent setting that attribute for that action. It works only for the actions you remember protecting.
However, this practice doesn't protect you from abuse using all the methods automatically added for associations.
will leave you vulnerable for someone setting the
comments_ids
attribute, even when you delete thecomments
attribute from params.Since there are quite a lot of methods added for associations, and since they might change in the future, the best practice is to protect your attributes on the model using
attr_accessible
. This will stop these kind of attacks most effectively.@tokland你最后的评论在某种程度上是不正确的。除非您的网站将浏览器作为数据传入和传出的唯一入口点。
如果您的 Web 应用程序具有 API 或与其他 API 进行通信,则控制器级别的保护会留下漏洞,并且来自其他来源的所有数据都不会被清理或检查。我建议保持原样,在 application.rb 中打开批量分配保护,并改进 ActiveSupport FormHelpers 以像 Django/Python 风格一样工作。
@tokland your last comment is not correct to some extend. Unless your website has the browser as the only entry point where data comes in and goes out.
If your webapp has an API or communicates with other API's protection on the controller level leaves holes behind it and all data from other sources is not sanitised or checked. I recommend keeping the things as they are, turning on mass-assignment protection in application.rb and advancing ActiveSupport FormHelpers to work like Django/Python style.