首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 5 SQL注入

Rails 5 SQL注入
EN

Stack Overflow用户
提问于 2016-12-31 18:22:07
回答 1查看 6.2K关注 0票数 17

我已经在不同的线程,指南等上读了一段时间了。但所有的答案都是相互矛盾和矛盾的。

似乎有很多类似的方法,很多答案都说要用不同的方法。

  • 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查询,但允许我插入来自危险用户输入的参数。

我不能在这几个例子中使用AR,因为我正在做复杂的lat/long计算、聚合函数、复杂的子查询等等。

到目前为止,我已经尝试了两种方法:

方法1

对于这种方法,我不知道sanitize是否是上述方法中的最佳选择,或者它是否在100%的情况下有效。(我只使用Postgres )

代码语言:javascript
复制
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执行时间(这破坏了我的分析工具)。

代码语言:javascript
复制
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能力,我需要一个很好的库,我可以把它包含在我所有的项目中,我知道这是完全安全的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-03 21:31:37

使用quote是安全的。我在the page you linked to上读到了答案,没有人说quote是不安全的。我看到你关于使用“引号”的问题了。是的,如果您只是在字符串周围加上引号,这是不安全的,例如:

代码语言:javascript
复制
q = "SELECT * FROM users where email = '#{params[:email]}'"

但是使用quote (方法)是很好的:

代码语言:javascript
复制
q = "SELECT * FROM users where email = #{connection.quote(params[:email])}"

你可以在控制台里玩,尽力打破它,但我不认为你能做到:

代码语言:javascript
复制
2.3.3 :003 > ActiveRecord::Base.connection.quote("f''oo")                                                                              
 => "'f''''oo'"

如果你成功了,我相信Rails团队会想知道(私下)!但是正如您所看到的,quote方法所做的不仅仅是在开头和结尾加上一个引号。

此外,由于您说您正在寻找权威引用,源代码本身的评论表明引用用户输入是这些函数的目的:

adapters/abstract/quoting.rb#L6-L13

代码语言:javascript
复制
# 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

代码语言:javascript
复制
# 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

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41410752

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档