提问人:user3494179 提问时间:4/6/2022 最后编辑:JISTuser3494179 更新时间:2/8/2023 访问量:442
这是否容易受到 sql 注入的影响?
Is this vulnerable to sql injection or not?
问:
在寻找解决问题的方法时,我发现了这个主题:
Rails 和 Arel 和 Scopes - 简化同一表/字段匹配上的多个 OR
其中一个答案是这样的:
fields = ["name", "email", "phone", "business_name", "doc_id"]
filter = fields.map { |field| "lower(#{field}) LIKE '#{term.downcase}'" }.join(' OR ')
@customers = Customer.where(filter)
但是,如果 term 是用户输入的参数,这是否容易受到 sql 注入的影响?如果是这样,我怎样才能让它成为 sql 注入证明?sanitize_sql_like能解决sql注入问题吗?所以像这样:
filter = fields.map { |field| "lower(#{field}) LIKE '#{sanitize_sql_like(term.downcase)}'" }.join(' OR ')
@customers = Customer.where(filter)
更新: 这是解决方案吗?
fields = ["name", "email", "phone", "business_name", "doc_id"]
filter = fields.map { |field| "lower(#{field}) LIKE :query" }.join(' OR ')
@customers = Customer.where(filter, query: "%#{sanitize_sql_like(term.downcase)}%")
答:
3赞
max
4/6/2022
#1
将用户输入插入 SQL 字符串的任何情况都是潜在的 SQL 注入漏洞。转义输入(这是sanitize_sql_like所做的)可以在一定程度上缓解它,但最好使用绑定变量将用户输入单独传递到数据库,这样它就不会被误解为实际命令。
# bad
User.where("email like %#{params[:email]}%")
# good
User.where("email like ?", "%#{params[:email]}%")
您也不需要手动构造那个巨大的 SQL 字符串。相反,只需创建一个 ActiveRecord::Relations 数组,并使用该方法将它们连接在一起。.or
fields = %w{ name email phone business_name doc_id }
filters = fields.map do |field|
Customer.where("lower(#{field}) LIKE :term", term: term.downcase)
end
@customers = filters.drop(1).inject(filters.first) do |memo, scope|
memo.or(scope)
end
这可能看起来有些令人生畏,但它实际上只是一个花哨的裤子版本:
Customer.where("lower(name) LIKE :term", term: term.downcase)
.or(
Customer.where("lower(email) LIKE :term", term: term.downcase)
)
.or(
Customer.where("lower(phone) LIKE :term", term: term.downcase)
)
# ...
评论
0赞
max
4/6/2022
您可以像在链接的答案中一样使用 Arel 的 matches 方法,但请注意,除非您传递 Arel::Nodes::BindParam 或 Arel::Nodes::SqlLiteral,否则它实际上会将用户输入插入 SQL 查询
0赞
user3494179
4/7/2022
感谢您的回复。第一部分 (fields.map { |field| <query> } -> 每次迭代是产生 1 db 事务还是 1 个事务?第二部分(filters.drop(1).inject(filters.first)看起来并不直观。如果其他开发人员想要处理它,他或她可能不会立即理解它。它与filters.flatten.compact做同样的事情吗?
0赞
max
4/7/2022
是的,它创建单个 ActiveRecord 关系,从而创建单个查询。 并且用于展平嵌套数组并删除 NIL,因此它没有可比性。如果您担心维护问题,请注释代码...flatten
compact
0赞
max
4/7/2022
inject
实际上是一种循环方法,有点像每个方法,只是它为块的每次迭代生成修改后的备忘录。对于任何有经验的 Ruby 开发人员来说,这并不是什么陌生的事情。
0赞
TonyArra
4/14/2022
@max我相信您也可以通过使用 Customer.none 初始化 inject/reduce 在单个块中完成此操作
评论