【问题标题】:ActiveRecord::Base.connection.select_all and sql injectionActiveRecord::Base.connection.select_all 和 sql 注入
【发布时间】:2015-07-23 08:23:14
【问题描述】:

在我的 Rails 应用程序中,我有一些在我的类中运行的 sql 函数。函数名为“survey_loader”

CREATE OR REPLACE FUNCTION survey_loader
  a lots of sql here
END;
$$;

我还有一些门面类来运行这些功能:

# Facade class to expose db stored procedures called from ruby code
class Procedure
  def self.survey_result_loader(administration_ids, survey_result_set_id)
    procedure_name = 'survey_loader'
    params = "some params here"

    select_all(procedure_name, params)
  end

  # Runs SQL function
  def self.select_all(procedure_name, params)
    result = ActiveRecord::Base.connection.select_all("SELECT #{procedure_name}(#{params});")
    success?(result, procedure_name)
  end

  def self.success?(result, key)
    result.first[key] == 't' ? true : false
  end
end

但是这段代码容易受到sql注入的影响,因为参数将由用户传递:

ActiveRecord::Base.connection.select_all("SELECT #{procedure_name}(#{params});")

如何重写它以更安全?

【问题讨论】:

  • 您需要重构它以使用where 查询而不是connection.select_all。您能否添加(针对您的问题,而不是评论)您将获得的参数种类和您想要进行的查询种类的一些示例?

标签: sql ruby-on-rails ruby activerecord


【解决方案1】:

首先,我建议您使用以下类设计结构来定义您的命名函数。它使用 Arel:

def self.survey_loader(params)
  @survey_loader = Arel::Nodes::NamedFunction.new('survey_loader', params)
end

其次,由于您在 Procedure 类中有硬编码的函数名称,因此您可能可以重写您的 self.select_all 方法,如下所示:

def self.select_all(active_record_model, params)
    active_record_model.select(survey_loader(params))
end

active_record_model 是您的类,您将使用存储过程对其执行查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 2019-12-06
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多