JDBC驱动程序为准备好的语句转义参数?
Posted
技术标签:
【中文标题】JDBC驱动程序为准备好的语句转义参数?【英文标题】:JDBC driver escaping arguments for prepared statement? 【发布时间】:2014-03-21 21:17:08 【问题描述】:来自OWASP page on Preventing SQL Injection in Java:
作为参数传递给准备好的语句的变量将被 JDBC 驱动程序自动转义。
我了解准备好的语句如何将用户输入作为参数内容而不是作为 SQL 命令的一部分进行处理。但是我偶然发现了上面引用的句子,我想知道所有的转义是什么。这如何帮助防止注入攻击?
【问题讨论】:
【参考方案1】:假设你的陈述是
"select * from foo where name = '" + name + "'";
现在,如果 name 变量恰好是 O'Reilly,您最终会得到以下 SQL 查询,这是无效的:
select * from foo where name = 'O'Reilly'
改用准备好的语句:
"select * from foo where name = ?"
然后驱动程序会将参数正确绑定为字符串,并且 O'Reilly 中的单引号不会被解释为以 'O
开头的字符串的结尾。
在这种简单的情况下,不使用准备好的语句“只会”导致您的应用出现异常。但是如果有人使用类似的名字
' or 1 = 1 or name <> '
查询将变为
select * from foo where name = '' or 1 = 1 or name <> ''
因此查询将加载表的每一行。这就是 SQL 注入的全部意义所在。
【讨论】:
我的名字是' or 1=1;delete from foo where id>0;select * from foo where name='
会更好
@vanOekel:但是有没有数据库驱动程序接受一次执行多个语句?
如果你使用准备好的语句则不行,但是如果你懒惰并使用connection.createStatement().execute(query)
,驱动程序可以允许多条语句(我在单元测试中使用它来一次性插入多条记录)。跨度>
谢谢,我明白什么是 sql 注入 - 但想知道为什么转义会阻止 sql 注入攻击,所以我明白了 - 它没有
确实如此。因为撇号不再被解释为查询的一部分。它们被解释为查询参数值的一部分。简而言之,准备好的语句改为执行以下查询:select * from foo where name = 'O''Reilly'
。自己尝试一下,看看会发生什么。以上是关于JDBC驱动程序为准备好的语句转义参数?的主要内容,如果未能解决你的问题,请参考以下文章
SQLITE JDBC 驱动程序准备好的语句失败(内部指针 0)