【问题标题】: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

【问题讨论】:

    标签: sql sql-injection


    【解决方案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 服务器解析。到那时任何恶意内容改变查询逻辑都为时已晚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-23
    • 2019-12-11
    • 2021-10-06
    相关资源
    最近更新 更多