使用绑定变量时,如何进行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";
将返回0行。
我在互联网上搜索了这个问题甚至是这个网站的答案,但我找不到它。
再次感谢。
答案 0 :(得分:4)
查询参数不可能" break"并在参数化查询中允许SQL注入。但是,参数绑定不能为所有可能的动态查询提供解决方案。也许那就是你的DBA意味着什么(为什么不问她?)。
考虑这个问题:
SELECT CUST_ID FROM CUST.CUSTOMER ORDER BY :COLUMNNAME :DIRECTION
请参阅,我们可能正在编写一个用户界面,允许用户选择要排序的列,以及方向,升序与降序。
但是你不能这样使用绑定参数。绑定参数可用于替换SQL表达式中的常量值,但不能替换表名,列名,SQL ASC
/ DESC
等SQL关键字或语法的其他部分。只有常量值,如带引号的字符串,带引号的日期文字或数字文字。
那么如何使用绑定参数来保护查询中需要动态的其他部分呢?
你不能!
在准备查询之前,必须在查询字符串中修复查询的其他部分,如标识符,SQL关键字或表达式。这意味着您无法使用参数占位符。
有一些技术,例如白名单,以确保您在SQL查询字符串中插入的变量属于一组已知值,并且这是引用标识符的标准方法,但其他方法并不是与绑定参数相同。
您可能会喜欢我的演示文稿SQL Injection Myths and Fallacies。这是我录制的一个网络研讨会录音:https://www.youtube.com/watch?v=VldxqTejybk
答案 1 :(得分:3)
如果您准备语句并将所有参数绑定到它,则可以确保无法进行SQL注入。这是因为这种工作方式没有向SQL中注入任何东西,所以不可能有 SQL注入。
首先编译SQL语句,然后将参数传递给数据库引擎。那时SQL文本不再扮演任何角色,而是它的编译版本。引擎知道如何处理这两个信息:编译语句和参数。它不将参数注入到某个SQL中,这在那时不再起作用了:它已经被编译了。
答案 2 :(得分:1)
说到常规查询, Mysql / PDO two known edge cases与Oracle无关。
说到存储过程,存储过程本身当然有could be a problem ,但我认为这是一个不相关的情况或不一致的使用预准备语句。
所以你的DBA很可能只是在某个地方听到了一些谣言,但对他所谈论的内容并不了解。
答案 3 :(得分:1)
严格来说,使用绑定变量时确实可以使用 SQL注入。 使用 BV 下方的查询可以 SQL注入 。
'select' + column_list + ' from T where col :1'
所以缺少的是在静态查询中使用绑定变量 。
答案 4 :(得分:-3)
如果你想对如何做到这一点有一个疯狂的推测,那就是:
execute immediate
...或基本上任何其他涉及将动态SQL与由用户提供的数据组成的查询字符串一起使用的代码。即使绑定参数也无法帮助你。