我已经在不同的线程,指南等上读了一段时间了。但所有的答案都是相互矛盾和矛盾的。
似乎有很多类似的方法,很多答案都说要用不同的方法。
sanitizesanitize_conditionssanitize_sqlsanitize_sql_arraysanitize_sql_for_assignmentsanitize_sql_for_conditionssanitize_sql_hashsanitize_sql_hash_for_assignmentsanitize_sql_hash_for_conditionssanitize_sql_like我试图编写一个“原始查询”适配器,它允许我运行原始Postgres查询,但允许我插入来自危险用户输入的参数。
我不能在这几个例子中使用AR,因为我正在做复杂的lat/long计算、聚合函数、复杂的子查询等等。
到目前为止,我已经尝试了两种方法:
方法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能力,我需要一个很好的库,我可以把它包含在我所有的项目中,我知道这是完全安全的。
发布于 2017-01-03 21:31:37
使用quote是安全的。我在the page you linked to上读到了答案,没有人说quote是不安全的。我看到你关于使用“引号”的问题了。是的,如果您只是在字符串周围加上引号,这是不安全的,例如:
q = "SELECT * FROM users where email = '#{params[:email]}'"但是使用quote (方法)是很好的:
q = "SELECT * FROM users where email = #{connection.quote(params[:email])}"你可以在控制台里玩,尽力打破它,但我不认为你能做到:
2.3.3 :003 > ActiveRecord::Base.connection.quote("f''oo")
=> "'f''''oo'"如果你成功了,我相信Rails团队会想知道(私下)!但是正如您所看到的,quote方法所做的不仅仅是在开头和结尾加上一个引号。
此外,由于您说您正在寻找权威引用,源代码本身的评论表明引用用户输入是这些函数的目的:
adapters/abstract/quoting.rb#L6-L13
# Quotes the column value to help prevent
# {SQL injection attacks}[http://en.wikipedia.org/wiki/SQL_injection].
def quote(value)adapters/postgresql/quoting.rb#L17-L20
# Quotes strings for use in SQL input.
def quote_string(s) #:nodoc:(请注意,我正在为注释显示quote_string,但您可能应该使用quote,它试图找出数据类型并做一些适当的事情。)
顺便说一句,这里有一个与你类似的问题,我在2014年给出了一个答案,还有一些选择:How to execute a raw update sql with dynamic binding in rails
https://stackoverflow.com/questions/41410752
复制相似问题