我已经阅读了很多关于此的内容,并且知道这里有很多相关的问题,但是我找不到有关如何对所有内容进行 sanitizer 的权威指南。一种选择是在插入时进行 sanitizer ,例如我的模型中有以下内容
before_validation :sanitize_content, :on => :create
def sanitize_content
self.content = ActionController::Base.helpers.sanitize(self.content)
end
我需要在每个模型的每个字段上运行它吗?我猜 :on => :create 也应该被删除,以便它在更新时也运行?
另一个选项是在 View 中显示数据时进行清理,使用 simple_format、.html_safe 或 sanitize(fieldname)。我应该对每个字段以及插入时的所有 View 进行 sanitizer 吗?必须在任何地方手动执行此操作似乎不是很麻烦
谢谢你的帮助
最佳答案
TL;DR
关于用户输入和查询:确保始终使用事件记录查询方法(例如 .where
),并避免使用字符串插值传递参数;将它们作为散列参数值或参数化语句传递。
关于呈现可能不安全的用户生成的 html/javascript 内容:从 Rails 3 开始,html/javascript 文本会自动正确转义,使其在页面上显示为纯文本,而不是解释为 html/javascript,因此您不需要显式清理(或使用 <%= h(potentially_unsafe_user_generated_content)
%>
如果我对您的理解正确,您无需担心以这种方式清理数据,只要您正确使用事件记录查询方法即可。例如:
假设我们的参数映射看起来像这样,因为恶意用户将以下字符串输入到 user_name
field :
:user_name => "(select user_name from users limit 1)"
坏方法(不要这样做):
Users.where("user_name = #{params[:id}") # string interpolation is bad here
结果查询如下所示:
SELECT `users`.* FROM `users` WHERE (user_name = (select user_name from users limit 1))
以这种方式直接进行字符串插值会将参数值的文字内容与键
:user_name
进入查询而不进行清理。您可能知道,恶意用户的输入被视为普通的 SQL,其危险性非常明显。好方法(这样做):
Users.where(id: params[:id]) # hash parameters
或
Users.where("id = ?", params[:id]) # parameterized statement
结果查询如下所示:
SELECT `users`.* FROM `users` WHERE user_name = '(select user_name from users limit 1)'
如您所见,Rails 实际上会为您清理它,只要您将参数作为散列或方法参数传递(取决于您使用的查询方法)。
在创建新模型记录时对数据进行清理的情况并不真正适用,因为
new
或 create
方法需要一个哈希值。即使您尝试将不安全的 SQL 代码注入(inject)散列,散列的值也会被视为纯字符串,例如:User.create(:user_name=>"bobby tables); drop table users;")
查询结果:
INSERT INTO `users` (`user_name`) VALUES ('bobby tables); drop table users;')
所以,情况和上面一样。
我希望这会有所帮助。如果我错过或误解了什么,请告诉我。
编辑
关于转义 html 和 javascript,简短的版本是 ERB 为您“转义”您的字符串内容,以便将其视为纯文本。如果你真的想要,你可以让它像 html 一样对待,通过执行
your_string_content.html_safe
.但是,只需执行
<%= your_string_content %>
之类的操作即可非常安全。内容被视为页面上的字符串。事实上,如果您使用 Chrome 开发人员工具或 Firebug 检查 DOM,您实际上应该看到该字符串周围的引号。
关于ruby-on-rails-4 - 在 Rails 中清理用户输入的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21886170/