使用绑定变量时 SQL 注入是如何实现的?

How is SQL Injection Possible When Using Bind Variables?

如何在使用绑定变量时进行 SQL 注入?

我的 DBA 说使用绑定变量并不能完全防止 SQL 注入,但我不知道这是怎么回事,因为绑定变量尤其是字符串通常会强制注入 SQL 成为 WHERE 子句中的字符串。

示例:

SELECT CUST_ID  
FROM CUST.CUSTOMER 
WHERE FIRST_NAME=:FNAME;

如果FNAME="SELECT FNMAME WHERE CUST_ID=10040",数据库会运行下面的查询

SELECT CUST_ID 
FROM CUST.CUSTOMER 
WHERE FIRST_NAME="SELECT FNMAME WHERE CUST_ID=10040";

这将 return 0 行。

我在 Internet 上搜索了这个问题的答案,甚至搜索了这个网站,但我找不到。

再次感谢。

查询参数不可能 "break" 并允许 SQL 在参数化查询中注入。但参数绑定确实没有为所有可能的动态查询提供解决方案。也许这就是您的 DBA 的意思(您为什么不问她?)。

考虑这个查询:

SELECT CUST_ID FROM CUST.CUSTOMER ORDER BY :COLUMNNAME :DIRECTION

看,我们可能正在编写一个用户界面,允许用户选择排序的列和方向,升序还是降序。

但是你不能这样使用绑定参数。绑定参数可用于替换 SQL 表达式中的常量值,但不能替换 table 名称、列名、SQL 关键字,如 ASC/DESC , 或语法的其他部分。仅常量值,例如带引号的字符串、带引号的日期文字或数字文字。

那么如何使用绑定参数来保护需要动态查询的其他部分?

你不能!

查询的其他部分,例如标识符、SQL 关键字或表达式,必须在您准备查询之前固定在查询字符串中。这意味着您不能为它们使用参数占位符。

有白名单等技术可以确保您在 SQL 查询字符串中插入的变量在一组已知值中,并且有一种引用标识符的标准方法,但其他方法不是与绑定参数相同。

你可能会喜欢我的介绍SQL Injection Myths and Fallacies. Here's a recording of me presenting it as a webinar: https://www.youtube.com/watch?v=VldxqTejybk

您可以放心,如果您准备语句并将所有参数绑定到它,SQL 注入是不可能的。这是因为这种工作方式不会向SQL注入任何东西,所以不可能有SQL注入 ].

首先编译SQL语句,然后将参数传递给数据库引擎。那时 SQL 文本不再起作用,而是它的编译版本。引擎知道如何处理这两条信息:编译语句和参数。它 将参数注入一些 SQL,这在那时不再起作用:它已经被编译了。

如果您想对这样的事情怎么可能进行疯狂的猜测,这里有一个:

  • 您插入 table,使用绑定参数
  • DBA 已经在 table
  • 上创建了一个插入触发器
  • 该触发器获取插入的值并将其用于 execute immediate

... 或基本上涉及使用动态 SQL 以及由用户提供的数据组成的查询字符串的任何其他代码。即使是绑定参数也帮不了你。

说到常规查询,two known edge cases Mysql/PDO 都与 Oracle 无关。

说到存储过程,存储过程本身当然有 ,但我认为这要么是无关紧要的情况,要么是预处理语句的使用不一致.

所以您的 DBA 很可能只是在某个地方听到了一些谣言,但不太清楚他在说什么。

严格来说SQL注入在使用绑定变量时确实是可能的。下面的查询 use BV and can be subject of SQL injection 以防参数 column_list 被操纵。

 'select' + column_list + ' from T where col :1'

所以缺少的是在静态查询中使用绑定变量 并避免使用参数 的语句连接,例如对于列列表。