【问题标题】:How to properly parameterize my postgresql query如何正确参数化我的 postgresql 查询
【发布时间】:2021-03-26 17:35:18
【问题描述】:

我正在尝试参数化我的 postgresql 查询,以防止我的 ruby​​ on rails 应用程序中的 SQL 注入。 SQL 查询将根据输入对我的表中的不同值求和。

这是我的函数的简化版本:

def self.calculate_value(value)
    calculated_value = ""
    if value == "quantity"
        calculated_value = "COALESCE(sum(amount), 0)"
    elsif value == "retail"
        calculated_value = "COALESCE(sum(amount * price), 0)"
    elsif value == "wholesale"
        calculated_value = "COALESCE(sum(amount * cost), 0)"
    end
    
    query = <<-SQL
        select CAST(? AS DOUBLE PRECISION) as ? from table1
    SQL
    return Table1.find_by_sql([query, calculated_value, value])
end

如果我调用calculate_value("retail"),它将执行如下查询:

select location, CAST('COALESCE(sum(amount * price), 0)' AS DOUBLE PRECISION) as 'retail' from table1 group by location

这会导致错误。我希望它在没有这样的引号的情况下执行:

select location, CAST(COALESCE(sum(amount * price), 0) AS DOUBLE PRECISION) as retail from table1 group by location

我知道添加引号是防止 sql 注入的原因,但在这种情况下我将如何防止它呢?处理这种情况的最佳方法是什么?

注意:这是我将要编写的查询的简化版本,我想使用 find_by_sql。

【问题讨论】:

  • 标识符需要双引号,单引号是或值。
  • 别名不能是参数。而且,它必须是一个常数——动态输出结构不是确定性的。建议 - 创建 3 个单独的最终非参数化查询文本,并根据提供的参数选择其中一个。

标签: postgresql sql-injection


【解决方案1】:

准备好的语句不能改变查询结构:表名或列名、order by 子句、函数名等。这种方式只能更改文字。

SQL 注入在哪里?您不会在查询文本中放置用户定义的值。相反,您根据允许的列表检查给定值并仅使用您自己编写的 SQL 部分。在这种情况下,不存在 SQL 注入的危险。


我也想链接到this article。如果您控制查询的所有部分,则动态创建查询文本是安全的。而且对于 RDBMS 来说,它比查询中的一些智能逻辑要好得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多