依靠参数化查询是防止SQL注入的唯一方法吗?


13

我对SQL注入攻击的所有了解似乎都表明,参数化查询(尤其是存储过程中的参数化查询)是防范此类攻击的唯一方法。在我工作的时候(回到黑暗时代),存储过程被认为是一种不好的做法,主要是因为它们的可维护性较差。可测试性较低;高度耦合;并将系统锁定在一个供应商中;(此问题涵盖其他一些原因)。

尽管在我工作时,项目实际上并没有意识到这种攻击的可能性。采用了各种规则来保护数据库免受各种损坏。这些规则可以概括为:

  1. 没有客户端/应用程序可以直接访问数据库表。
  2. 对所有表的所有访问都是通过视图进行的(对基本表的所有更新都是通过触发器进行的)。
  3. 所有数据项都有指定的域。
  4. 不允许任何数据项为空-这意味着DBA有时会磨牙。但被执行了。
  5. 角色和权限已适当设置-例如,受限制的角色仅授予视图更改数据的权利。

那么,这样的一组(强制)规则(尽管不一定是特定的一组)是否可以替代参数化查询,以防止SQL注入攻击?如果没有,为什么不呢?可以通过(仅)数据库特定措施来保护数据库免受此类攻击吗?

编辑

鉴于收到的初步答复,对该问题的重视程度略有变化。基本问题不变。

编辑2

依赖参数化查询的方法似乎只是防御系统攻击的外围步骤。在我看来,更基本的防御措施既可取,又可能使对此类查询的依赖变得不必要或不太关键,甚至可以专门防御注入攻击。

我的问题中隐含的方法基于“加固”数据库,我不知道它是否是可行的选择。进一步的研究表明存在这样的方法。我发现以下来源提供了一些指向这种方法的指针:

http://database-programmer.blogspot.com

http://thehelsinkideclaration.blogspot.com

我从这些来源获得的主要特征是:

  1. 广泛的数据字典,与广泛的安全数据字典相结合
  2. 从数据字典生成触发器,查询和约束
  3. 最小化代码并最大化数据

尽管我到目前为止所获得的答案非常有用,并指出了忽略参数化查询所带来的困难,但最终它们并没有回答我的原始问题(现在以粗体强调)。


我不反对存储过程。他们根本不是真的。
康拉德·鲁道夫

无空要求是怎么回事?
Mark Canlas

2
@Konrad Rudolph-如果您在MySQL上编写应用程序,然后决定迁移到DB2,您真的认为存储过程将兼容吗?同样是否要迁移到SQLLite?另外,假设您升级了操作系统-如果您的存储过程是用C编译的(它们在DB2中),那么它们可能都需要重新编译。这些是合理的论点-不是绝对的,而是合理的。
马修·弗林

@Matthew Duh。在阅读和评论时,我实际上是在考虑“参数化查询”。存储过程=整个故事。
康拉德·鲁道夫

Answers:


25

存储的过程不会自动防止注入。那这个呢

CREATE PROC proc
  @id VARCHAR(5)
AS
BEGIN
  EXEC("SELECT * FROM Client WHERE ClientId = " + @id);
END

使用参数化查询可以防止注入,无论它们是否在proc中。


感谢您关注参数化查询,而不是过程。但是,我要问的是,是否可以通过除此类查询以外的方法来保护数据库-特别是仅限于数据库层的方法。
克里斯·沃尔顿

1
+1除此之外,我想指出一下,存储的proc大多被认为是安全的,因为这是阻止用户直接访问表的同时仍保持检索数据的唯一方法。当用户需要直接与客户端进行数据库访问而中间没有任何访问权限时,这是确保基于行和基于列的特权的唯一方法。
猎鹰

2
@Chris-我认为Craig在这里所说的是,您不能认为proc确实可以保护您。这可能不是一个完整的答案,更多是标题中假设的更正。
乔恩·霍普金斯,

@Jon-根据Craig的更正,我更改了问题的标题,并对问题进行了一些编辑。在开始收到答复之前,我不知道自己在问题中所做的假设。
克里斯·沃尔顿

2
要加强Craig在上面的内容,请参见 databasesecurity.com/dbsec/lateral-sql-injection.pdf,“横向SQL注入:Oracle中的新型漏洞”
Bruce Ediger

11

那么,诸如此类的一组(强制)规则是否可以替代存储过程,从而防止SQL注入攻击?如果没有,为什么不呢?

不,因为它们对开发人员造成了相当大的惩罚。按项目细分:

1.没有客户端/应用程序可以直接访问数据库表。

使用角色。客户端只能通过受限制的角色访问数据库,该角色仅具有对其需要访问的表(以及行,如果可能)的SELECT,INSERT,UPDATE和DELETE访问权限。如果要确保没有客户端可以发送垃圾邮件或删除所有条目,请使用API​​进行数据修改。

2.对所有表的所有访问均通过视图进行。

根据视图的效率,这可能是可忽略不计的,也可能是巨大的性能成本。不必要的复杂性会减慢开发速度。使用角色。

3.所有数据项都有指定的域。

可能需要维护很多工作,应该将其标准化为单独的表。

4.不允许任何数据项为空–这意味着DBA有时会磨牙。但被执行了。

那是完全错误的。如果开发人员无法处理NULLs,那么您将遇到很大的问题。

可以通过(仅)数据库特定措施来保护数据库免受此类攻击吗?

不是需要的存储过程,只需要使用参数化查询与逃脱的参数,如功能pg_query_params。当然,如果您的数据库是世界可写的,或者客户端角色具有对所有内容的完全访问权限,那么无论如何您都会被搞砸。只需有人意识到客户在做什么,然后在五分钟之内煮熟一个客户,这会破坏(或更糟的是,毒害您的)数据库。



+1代表角色。它们是对此的主要贡献者-我没有在角色中包括角色,但它们是设置的一部分-特别是为视图分配了受限角色,例如您为客户建议的角色。点对性能的影响很大。域包括验证测试-主要是范围和长度。您对数据可为空的规则的评论比我所听到的有关此规则的评论要客气得多。尽管这是我的假设,但我并未明确声明将适当地设置权限。
克里斯·沃尔顿

6

我不确定您的规则是否会完全保护您。

第一个问题是,您说他们已经得到执行,但是,除了开销很大之外,我还从未见过完美的执行。

其次,我对它们的理解是,像这样的规则可能会使事情难以利用,但并不能阻止它。例如,如果视图允许您访问相同的数据,则没有直接访问表的权限实际上并没有太大变化。如果客户端需要执行某项操作,则需要一个视图来促进该操作,并且如果一个视图可以促进该操作,则攻击者可以利用相同的功能/数据。

还要记住,这不只是更新或删除数据。SQL注入漏洞的一部分是信息收集,因此您不必担心数据是否已通过视图vCustomers或基础客户表传回。您可能已经保护自己免受某些弱点,但不是全部。同样,如果客户端可以进行更新(即使通过触发器),则可以编写SQL来触发触发器并进行更新。

(就通过触发器完成的所有更新而言,我要说两件事:(1)当我读到这篇文章时,我的嘴巴有点不适,(b)您不喜欢存储过程,因为它们re“缺乏可维护性;较少测试性;高度耦合;并且将系统锁定在一个供应商中”,但您确实使用触发器,关于触发器基本上可以说相同的话。)

您所需要的只是一个漏洞,该漏洞允许执行SQL语句(并且我看不到任何阻止其执行的规则),并且攻击者处于其中。他们可能正在其后发现一个非常不直观的数据库,但如果确定这样做会只会减慢速度而不是停止它们)。

这里的另一件事是,您还会增加复杂性,并且(以及所产生的开销)复杂性往往会导致漏洞被利用。

我并不是说无法创建这样的规则集-更何必打扰您?与仅采用防止这种攻击的广为接受的方法相比,它们似乎更麻烦,更不可靠。


+1可根据我的隐含,无意识的假设理解我的实际查询,并适当地对其进行响应。至于为什么会打扰-我正在一个项目中,将从该体系结构的相关描述中生成很多代码-并且该体系结构的一部分描述了如何生成数据库访问例程。这些生成的例程将采用何种形状仍是公开的。
克里斯·沃尔顿
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.