我已经阅读了一段时间,现在在各种SO线程,指南等,但所有的答案是相互矛盾和矛盾的。Rails 5 SQL注入
看来有很多类似的方法,并且很多答案都表示使用不同的方法。
sanitize
sanitize_conditions
sanitize_sql
sanitize_sql_array
sanitize_sql_for_assignment
sanitize_sql_for_conditions
sanitize_sql_hash
sanitize_sql_hash_for_assignment
sanitize_sql_hash_for_conditions
sanitize_sql_like
我想写一个“原始查询”适配器,让我跑生Postgres的查询,但允许我插入我自己的参数来自于危险的用户输入。
,因为我在做复杂的纬度/长计算,聚合函数,子查询复杂等
到目前为止,我已经试过2点的方法,我不能在这些少数情况下使用AR:
方法1
对于这种方法,我不知道是否sanitize
是上述的最佳选择,或是否会在案件100%的工作...(我使用的是Postgres只)
class RawQuery
def exec(prepared, *params)
prepared = query.dup
params.flatten.each_with_index do |p, i|
prepared.gsub!("$#{i + 1}", ActiveRecord::Base.sanitize(p))
end
ActiveRecord::Base.connection.exec_query(prepared)
end
end
琐碎的使用实例(通常它不会是这个简单的当然还是我只想用AR):
RawQuery.new.exec('SELECT * FROM users WHERE name = $1', params[:name])
而且似乎sanitize
委托给quote
。但根据this SO post它只是简单地用单引号包装的东西是不安全的......所以我不知道。
方法2
我不知道这是否是一样安全,但它似乎用实际PG准备功能(我假设是100%安全的)。唯一的问题是,rails不会将它打印到控制台,也不包括SQL执行时间(这会中断我的分析工具)。
class RawQuery
def prepare(query, *params)
name = "raw_query_#{SecureRandom.uuid.gsub('-', '')}"
connection = ActiveRecord::Base.connection.raw_connection
connection.prepare(name, query)
connection.exec_prepared(name, params)
end
end
用同样的方式:
RawQuery.new.prepare('SELECT * FROM users WHERE name = $1', params[:name])
是一个方法更安全了另一个?既100%安全?
我的应用程序总是远远超出Rails具有SQL能力的地方,我需要一个很好的lib,我可以将其包含在我所知道的所有项目中,这些项目我都是完全安全的。
我明白了 - 这很有道理。那么'sanitize'和'sanitize_sql_for_conditions'之间的主要区别是什么?另一个我忘了在我原来的问题中包含的部分是,'method sanitize_sql_for_conditions'的文档提到:*将它们清理成** WHERE **子句的有效SQL片段*。 'sanitize'的文档say *用于在对象用于SQL ** SELECT **语句*之前对对象进行清理。这是否意味着它们与情境有关,并且一种方法不能在SQL语句中的任何地方使用? (在SELECT,WHERE,GROUP BY等)。或者我可以使用'sanitize'无论位置? – Tallboy
它看起来像'sanitize_ *'方法都受到保护,所以我不认为你打算使用它们。我一直都把'quote'理解为这种事情的主要公共方法。事实上,简单的'sanitize'方法只是调用'quote'(正如你所说的)。看看代码,看起来像其他'sanitize_ *'方法真的是用于桥接Railsy数据结构(例如'{name:“foo”,email:“[email protected]”}')和'quote' 。他们为每个值调用'quote'。 '* for_conditions' vs'* for_assignment'似乎主要是关于使用','vs'AND'。 –
感谢您的帮助!很好的答案。 – Tallboy