2

感谢您的帮助,因为我引导我进入 Ruby 和 Rails。

ActiveRecord::Base的 Rails API 中,有一个关于条件的部分,旨在简单地介绍与 ActiveRecord 交互的语法。但是他们使用的示例包括(对我而言)非常有趣的关于 Ruby/Rails 中输入清理的入门:

class User < ActiveRecord::Base
  def self.authenticate_unsafely(user_name, password)
    where("user_name = '#{user_name}' AND password = '#{password}'").first
  end

  def self.authenticate_safely(user_name, password)
    where("user_name = ? AND password = ?", user_name, password).first
  end

  def self.authenticate_safely_simply(user_name, password)
    where(:user_name => user_name, :password => password).first
  end
end

按照此示例代码,他们解释说:

“authenticate_safely 和 authenticate_safely_simply 都将在将用户名和密码插入查询之前对其进行清理,这将确保攻击者无法逃避查询并伪造登录(或更糟)。”

我完全明白这种输入净化是如何防止注入攻击的好事。鉴于没有调用特殊方法来预处理输入数据,我不明白这种隐式清理的位置和方式。各种示例方法似乎具有几乎相同的语义,但由于它们的解析方式,形式上的变化对安全性产生了巨大影响。我假设这些形式上的变化在效果上类似于在包含转义字符的字符串周围使用单引号和双引号之间的区别。但是,任何人都可以通过一般性的理解(或者更确切地说:在逻辑层面,而不是在解释器内部)来帮助我变得更聪明、更快吗?

此外,这些差异在多大程度上依赖于特定于 Rails 的构造,而不是底层的 Ruby?

谢谢!

4

1 回答 1

3

输入清理是 Active Record 提供的一项功能,称为预准备语句或参数化语句

大多数数据库访问库本机提供此功能,但是,Active Record 选择 使用字符串处理机制来模拟此功能。查看build_whereinactive_record/relation/query_methods.rb并回溯到sanitize_sql_for_conditions(通过其sanitize_sql别名) in active_record/base.rb。(非常感谢mu 太短了,无法进行研究。)

与在应用程序中将查询字符串构建为字符串的旧式做法不同,您有一个带参数的静态模板查询。当您调用查询时,您提供参数,Active Record 将构造一个安全查询供 SQL 引擎执行。

您可以自己完成这项任务——无数 PHP 程序员选择避开他们类似的PDO 数据库访问层。然而,许多程序员无法正确理解这一点:在过去三年中发现了大约 1500 个 SQL 注入漏洞,而我的本地CVE 数据库显示,自 MITRE 开始跟踪以来,有超过 5000 个易受 SQL 注入攻击的程序实例。几乎所有这些都完全归因于那些选择手动编写自己的 SQL 代码并且没有正确清理输入的人。(我没有亲自检查每一个,但我不记得在 ORM 或数据库访问层中看到任何允许 SQL 注入攻击通过的缺陷。但为了保守起见,我选择了“几乎所有”。)

堆栈员Jeff Atwood 将旧式 SQL 查询等同于goto数据库编程

非参数化 SQL 是数据库编程的 GoTo 语句。不要这样做,并确保你的同事也不这样做。

于 2012-03-06T01:57:07.207 回答