我已经阅读了很多相关内容,并且知道这里有很多相关的问题,但是我找不到关于如何对所有内容进行消毒的明确指南。一种选择是对插入进行清理,例如我的模型中有以下内容
before_validation :sanitize_content, :on => :create
def sanitize_content
self.content = ActionController::Base.helpers.sanitize(self.content)
end
我是否需要在每个模型的每个字段上运行此操作?我猜是:on => :create也应该被删除,以便在更新时运行吗?
另一个选项是使用simple_format或.html_safe或sanitize(fieldname)在视图中显示数据时进行清理。我应该对每一个领域以及插入的所有观点进行消毒吗?必须在任何地方手动执行此操作似乎并不是很困难
感谢您的帮助
答案 0 :(得分:68)
<强> TL; DR 强>
关于用户输入和查询: 确保始终使用活动记录查询方法(例如.where
),并避免使用字符串插值传递参数;将它们作为哈希参数值传递,或作为参数化语句传递。
关于渲染可能不安全的用户生成的html / javascript内容:从Rails 3开始,html / javascript文本会自动正确转义,以便在页面上显示为纯文本,而非而不是解释为html / javascript,因此您不需要明确消毒(或使用<%= h(potentially_unsafe_user_generated_content)
%&gt;
如果我理解正确,只要您正确使用活动记录查询方法,就不必担心以这种方式清理数据。例如:
让我们说我们的参数映射看起来像这样,因为恶意用户将以下字符串输入user_name
字段:
: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代码注入到散列中,散列的值也会被视为纯字符串,例如:
User.create(:user_name=>"bobby tables); drop table users;")
查询中的结果:
INSERT INTO `users` (`user_name`) VALUES ('bobby tables); drop table users;')
所以,与上述情况相同。
我希望有所帮助。如果我错过或误解了任何内容,请告诉我。
修改强>
关于转义html和javascript,简短的版本是ERB&#34;逃避&#34;您的字符串内容,以便将其视为纯文本。如果你真的想要,你可以通过your_string_content.html_safe
将 视为html。
但是,简单地执行<%= your_string_content %>
之类的操作非常安全。内容在页面上被视为字符串。事实上,如果您使用Chrome开发者工具或Firebug检查DOM,您实际上应该看到该字符串周围的引号。
答案 1 :(得分:11)
因为我总是欣赏当我在任何SO答案中找到知识和代码的来源时,我将为此问题提供。
ActiveRecord和ActionController都提供了清理sql输入的方法。
具体来自ActiveRecord::Sanitization::ClassMethods
您有 sanitize_sql_for_conditions 及其他两个别名:
sanitize_conditions 和 sanitize_sql 。这三者确实完全相同。
sanitize_sql_for_conditions
接受SQL条件的数组,散列或字符串并进行清理 它们是一个有效的SQL片段,用于WHERE子句。
但是,在ActiveRecord中你也有
sanitize_sql_for_assignment
接受SQL条件的数组,散列或字符串并对其进行清理 到一个有效的SQL片段用于SET子句。
另一方面,ActionController docs here允许您ActionController::Parameters
选择哪些属性应列入白名单以进行批量更新 从而防止意外暴露不应暴露的东西。 为此提供了两种方法:需要和允许。
params = ActionController::Parameters.new(user: { name: 'Bryan', age: 21 })
req = params.require(:user) # will throw exception if user not present
opt = params.permit(:name) # name parameter is optional, returns nil if not present
user = params.require(:user).permit(:name, :age) # user hash is required while `name` and `age` keys are optional
参数magic称为强参数,DEMO。
我希望能帮助任何人,如果只是为了学习和揭开Rails的神秘面纱! :)