ruby-on-rails – Rails 5 SQL注入

我已经读了一段时间了,在各种各样的SO线程,指南等,但所有的答案是矛盾和矛盾的.

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

>消毒
> 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,因为我做复杂的长时间/长时间的计算,聚合函数,复杂的子查询等.

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

方法1

对于这种方法,我不知道清洁是否是上述的最佳选择,或者如果它在100%的情况下工作…(我仅使用Postgres)

class RawQuery

  def exec(prepared,*params)
    params.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])

此外,它似乎对2007年的代表进行了消毒.但根据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,我可以在我所知道的所有项目中包含完全安全的内容.

解决方法

使用报价是安全的我读了 the page you linked to的答案,我没有看到有人说这个报价是不安全的.我看到你使用“引号”的问题.是的,如果你只是在一个字符串上引用引号,那就是不安全的,例如:
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团队想知道(私下)!但是您可以看到,引用方法不仅仅是在开始和结束时引用一个引号.

另外,由于你说你正在寻找一个权威的引文,源代码本身的意见表明引用用户输入是这些功能的预期目的:

https://github.com/rails/rails/blob/2471e6391dfe71cfbb8621bdf573729d961d3209/activerecord/lib/active_record/connection_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)

https://github.com/rails/rails/blob/0f1d0b1b5254e3678abaabbebb3362a100c10262/activerecord/lib/active_record/connection_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

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...