传递键值对是不是也可以防止 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 注入攻击?的主要内容,如果未能解决你的问题,请参考以下文章