如何修复订单轨查询中的sql注入

How to fix sql injection in order rails query

提问人:shashantrika 提问时间:3/24/2021 最后编辑:shashantrika 更新时间:12/23/2021 访问量:1365

问:

我是 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-Rails Ruby SQL注入

评论

1赞 Jaffa 3/24/2021
什么例外?
0赞 shashantrika 3/24/2021
@Geoffroy : 添加了有问题的异常本身。

答:

1赞 Jaffa 3/24/2021 #1

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

在:

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

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

现在关于您的问题,在生成查询时不会替换参数,它根本无法像 .order?where

换句话说:使用你之前使用的代码,它运行良好,不受SQL注入的影响(只要你控制什么)PASSENGER_STATUS

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

评论

0赞 shashantrika 3/25/2021
谢谢你的回答。我将尝试更改我的查询。
4赞 spickermann 3/25/2021 #2

正如 Geoffroy 已经指出的那样,在您的特定示例中,不存在 SQL 注入的风险,因为输入数据在您的控制之下。

但是,尽管如此,你仍然可以在 Rails Docs 中找到sanitize_sql_for_order。文档中的示例与您的用例完全匹配:

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