传递键值对是不是也可以防止 SQL 注入攻击?

Posted

技术标签:

【中文标题】传递键值对是不是也可以防止 SQL 注入攻击?【英文标题】:Does passing in key value pairs also protect against SQL injection attacks?传递键值对是否也可以防止 SQL 注入攻击? 【发布时间】:2020-03-26 10:55:51 【问题描述】:

我遇到了这个示例,其中不使用绑定参数,而是将键值对传递给 heredoc。我知道这将允许用户以任何顺序输入输入,但我的问题是,如果我使用键值对而不是绑定参数,它是否仍然可以防止 SQL 注入攻击?如果没有,有没有办法让用户在没有任何特定顺序的情况下传递输入,同时还能防止注入攻击?

以下是使用键值对的示例:

def self.find_by_id(id)
    found_user = QuestionDatabase.instance.execute(<<-SQL, id: id)
      SELECT
        users.*
      FROM
        users
      WHERE
        users.id = :id
    SQL
    found_user.nil? ? nil : User.new(found_user)
  end

以下是使用绑定参数的示例:

def self.find_by_id(id)
    found_user = QuestionDatabase.instance.execute(<<-SQL, id)
      SELECT
        users.*
      FROM
        users
      WHERE
        users.id = ?
    SQL
    found_user.nil? ? nil : User.new(found_user)
  end

【问题讨论】:

【参考方案1】:

据我所知,没有将参数传递给heredoc 的语法。您所展示的实际上只是将哈希作为参数传递给execute()

Ruby 允许参数是标量、数组或散列。

require 'pp'

def execute(sql, binds)
        pp binds
end

id = 123

execute('blah blah blah', id: id)

execute('blah blah blah', id)

输出:

:id=>123
123

它实际上并没有将id 与字符串组合,它只是将它作为参数传递给execute() 函数。第一次,它传递一个哈希,所以你得到关联的键值对。第二次,它只是传递一个标量。

大概真正的 Rails execute() 方法有一些代码来检查传递的参数是标量还是散列,然后它会从 SQL 字符串中解析出命名参数占位符,如果你使用的 RDBMS 没有支持命名参数,它将它们替换为? 占位符。

无论哪种方式,SQL 注入都是安全的。

【讨论】:

啊,好吧,所以如果我理解正确的话,直接在 WHERE 子句中传递实例变量会使代码容易/容易受到 SQL 注入攻击,因为用户可能会输入恶意代码并且没有检查在使用该变量之前完成。但是事先检查符号和其他绑定变量是否存在恶意字符? SQL 注入只有在恶意内容可以被插入到查询中时才有效,当它是一个字符串,在它被 RDBMS 服务器解析之前。绑定变量与 SQL 查询字符串保持分离,直到 SQL 语法被 RDBMS 服务器解析。到那时任何恶意内容改变查询逻辑都为时已晚。

以上是关于传递键值对是不是也可以防止 SQL 注入攻击?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止网站不被SQL注入攻击

ASP.ENT中做登陆怎么防止注入攻击?

web开发中防止SQL注入

如何防止sql注入攻击?

如何有效防止SQL注入攻击

php中防止SQL注入,该如何解决?