如何修复 sql 注入顺序 Rails 查询

问题描述

我是 ruby​​ 新手,关注 this 博客修复了 sql 注入错误,但我的查询出错了。

原始查询

class Car < ActiveRecord::Base
  ...
  has_one :Driver,lambda {
     where(status: PASSENGER_STATUS,connected_number: [phone,mobile])
    .order("FIELD (`classDummy`.`status`,#{PASSENGER_STATUS.join(',')}")
  },class_name: :classDummy

而 PASSENGER_STATUS 是(在其他类中)

PASSENGER_STATUS = [
  'employed','temporary'
  ].freeze

sql 注入修复我做了

  order("FIELD (`classDummy`.`status`,? )",PASSENGER_STATUS.join(','))

但是这是在执行查询时抛出异常。

我得到的例外:

ActiveRecord::StatementInvalid: MysqL2::Error: 你的 sql 语法有错误;检查与您的 MysqL 相对应的手册 '?,

附近使用正确语法的服务器版本

解决方法

正如 Geoffroy 已经指出的那样,在您的具体示例中,没有 SQL 注入的风险,因为输入数据在您的控制之下。

但是,您可以在 Rails 文档中找到 sanitize_sql_for_order。文档中的示例与您的用例完全匹配:

sanitize_sql_for_order(condition)

接受一个数组或 SQL 条件字符串,并将它们清理为 ORDER 子句的有效 SQL 片段。

sanitize_sql_for_order(["field(id,?)",[1,3,2]])
# => "field(id,1,2)"

sanitize_sql_for_order("id ASC")
# => "id ASC"

使用这种方法你可以像这样编写你的关联:

has_one :Driver,lambda {
     where(status: PASSENGER_STATUS,connected_number: [phone,mobile])
       .order(sanitize_sql_for_order(["FIELD(`classDummy`.`status`,PASSENGER_STATUS])
},class_name: :classDummy
,

您阅读的博客是关于处理用户输入的,在这种情况下,防止 sql 注入非常重要。

在:

order("FIELD (`classDummy`.`status`,#{PASSENGER_STATUS.join(',')})")

您是 SQL 查询中的注入代码,但它是您控制的代码并且您确切地知道它是什么,因此不存在 SQL 注入的风险。

关于您的问题,order 在生成查询时不会替换参数 ?,它根本不像 where 那样工作。

换句话说:使用您之前使用的代码,它运行得非常好并且不受 SQL 注入的影响(只要您控制 PASSENGER_STATUS 是什么)

检查日志以查看发送到服务器的 SQL 查询,您将更好地了解发生了什么