Rails Brakeman:Arel 的 SQL 注入

Posted

技术标签:

【中文标题】Rails Brakeman:Arel 的 SQL 注入【英文标题】:Rails Brakeman: SQL Injection for Arel 【发布时间】:2021-07-18 00:21:16 【问题描述】:

我的user_ransaker.rb 文件中有以下代码:

ransacker :new_donors do
      sql = %(
              users.id IN (
                #User.new_donor_sql
              )
            )
      Arel.sql(sql)
    end

user.rb 模型上:

def self.new_donor_sql
    part_1 = %(
      SELECT distinct(user_id)
      FROM donations
    
    part_1
end

对于上述声明,我收到以下 Brakeman 警告:

Confidence: High
Category: SQL Injection
Check: SQL
Message: Possible SQL injection
Code: Arel.sql("(\n users.id IN (\n #User.new_donor_sql\n)\n)")
File: app/models/concerns/user_ransackers.rb

这是一个有效的错误吗?如果我使用 ActiveRecord 编写 SQL 语句,如果需要插入值,我可以使用 ? 占位符。我不确定如何解决此警告。如果这是一个有效的警告,我该如何补救?

【问题讨论】:

您使用 Arel 进行此查询是否有特殊原因?这可以通过 ActiveRecord 来完成。 我正在使用 Ransack gem。我正在做类似于文档中提到的第 2.2 点的事情:github.com/activerecord-hackery/ransack/wiki/Using-Ransackers。如果我使用 ActiveRecord,我会得到 undefined method 'eq' for .... 【参考方案1】:

如果你要 Arel 然后做一些关系代数:

class User < ApplicationRecord
  def self.new_donor_sql
    arel_table.project(arel_table[:user_id]).distinct
  end
end
ransacker :new_donors do
  User.arel_table.then do |users|
    users.where(users[:id].in(User.new_donor_sql)).where_sql
  end
end

你也可以直接删除类方法:

ransacker :new_donors do
  User.arel_table.then do |users|
    subquery = users.project(users[:user_id]).distinct
    users.where(users[:id].in(subquery)).where_sql
  end
end

【讨论】:

我收到undefined method then for #&lt;Arel::Table 您使用的是什么版本的 Ruby? Object#then 在 2.6 中作为 Object#yield_self 的别名引入 - 旧版本已停产。如果您确实必须为旧版应用程序使用旧版本,请分配一个变量而不是 users = User.arel_table; subquery = users.project(users[:user_id]).distinct; users.where(users[:id].in(subquery)).where_sql

以上是关于Rails Brakeman:Arel 的 SQL 注入的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3.0 中的 Arel 到底是啥?

如何在 Arel 和 Rails 中进行 LIKE 查询?

Rails Arel查询,在现在之前获取列一定的持续时间

ARel 模仿包含 find_by_sql

如何使用ARel对子查询进行连接?

Arel + Rails 4.2 导致问题(绑定丢失)