首页 > 解决方案 > 如何在 order rails 查询中修复 sql 注入

问题描述

我是 ruby​​ 的新手,并按照博客修复了 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 服务器版本相对应的手册,以了解在 '?, 附近使用正确的语法

标签: ruby-on-railsrubysql-injection

解决方案


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

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

sanitize_sql_for_order(condition)

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

sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
# => "field(id, 1,3,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

推荐阅读