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&gt;0;select * from foo where name='会更好 @vanOekel:但是有没有数据库驱动程序接受一次执行多个语句? 如果你使用准备好的语句则不行,但是如果你懒惰并使用connection.createStatement().execute(query),驱动程序可以允许多条语句(我在单元测试中使用它来一次性插入多条记录)。跨度> 谢谢,我明白什么是 sql 注入 - 但想知道为什么转义会阻止 sql 注入攻击,所以我明白了 - 它没有 确实如此。因为撇号不再被解释为查询的一部分。它们被解释为查询参数值的一部分。简而言之,准备好的语句改为执行以下查询:select * from foo where name = 'O''Reilly'。自己尝试一下,看看会发生什么。

以上是关于JDBC驱动程序为准备好的语句转义参数?的主要内容,如果未能解决你的问题,请参考以下文章

SQLITE JDBC 驱动程序准备好的语句失败(内部指针 0)

mssql-jdbc MS SQL Server JDBC 驱动程序准备好的语句缓存性能问题与 Hikari CP

如何使用 jdbc 准备好的语句传递可变数量的参数?

将字符串参数插入准备好的语句的问题

在android中使用JDBC安全可靠吗?

为啥使用 mysql 准备好的语句比使用常见的转义函数更安全?