2014-01-10 35 views
3

我们有一个Java应用程序,它与同一个 框中的多个SQL Server数据库进行通信。这些数据库的数量和名称各不相同。总的来说,我们几乎只用存储过程和CallableStatement来访问数据库。我们非常善于避免SQL注入和使用绑定变量。CallableStatement是否真的免疫SQL注入?

关注的唯一领域是数据库名称本身串连成我们传递给CallableStatement的这样的SQL:

"{call [" + dbName + ".dbo." + procName + "(?, ?, ?)}" 

PROCNAME是硬编码到使用模板方法模式的子类,以确保字符串安全。

dbName是外部定义的。我曾尝试将dbName设置为各种模式以避免语法,并在我的开发环境中利用此方法,但未成功。

我已经将它设置为以下出示下列SQL调用(表PROC名称更改为保护无辜者):

securitytest].nx_proc()};delete from poor_victim_table; 

成为

{call [securitytest].nx_proc()};delete from poor_victim_table;].dbo.proper_proc_name()} 

securitytest].nx_proc()};exec('delete from poor_victim_table'); 

变成

{call [securitytest].nx_proc()};exec('delete from poor_victim_table');].dbo.proper_proc_name(?,?,?,?,?,?,?)} 

结果在Incorrect syntax near ')'.poor_victim_table仍然有行。我已经使用truncate table,drop tabledrop database,当他们不工作时,我切换到简单delete排除安全设置。

如果我使用一个采用绑定参数的过程,我总会得到期望参数数量和提供的参数(如The index 1 is out of range.)之间的不匹配。

securitytest]};exec('delete from poor_victim_table'); 

成为

{call [securitytest]};exec('delete from poor_victim_table');].dbo.proper_proc_name(?,?,?,?,?,?,?)} 

所有的道路似乎导致运行时错误和SQL不执行。当然,这很好。但我想确保它失败,因为它不能不能成功,并没有失败,因为我没有尝试正确的组合。

流行的观点/都市神话是,使用存储过程使您免于SQL注入,但我更喜欢在安全方面不相信这样的绝对语句。

经过一段时间的研究,最好的我想出了这个计算器的问题:SQL injection - no danger on stored procedure call (on iSeries)?。它似乎支持使用CallableStatement,因为它可以保护您免受SQL注入攻击,除非您的proc代码本身将动态SQL从输入参数中取出。

所以,我对社区的问题是,假设proc中的SQL代码是安全的,那么在JDBC中使用CallableStatement是否真的阻止了SQL注入?或者SQL Server驱动程序以阻止它的方式解析字符串,但其他驱动程序可能不会?还是我不够努力?

如果是安全的,那么担保是如何做出的?是否由于使用{ call blah(?) }的抽象语法,这不是真正的SQL,而是被转换为SQL?

回答

2

应该是安全的,但就像你一样,我也不会相信,特别是如果你使用不同的JDBC驱动程序等

如果我是你的接口到不同的数据库,语句之前你发布了,我会确保检查dbName是否包含字母,数字和可能的下划线。这应该允许所有有效的dbNames,并防止各种混乱。

+0

我刚刚在你的帖子开始处看到你说过“diffeernt sql servers”,但没有设置任何特定标签,所以我不确定这是否意味着“MS SQL的不同实例”或“Oracle, DB2,Mysql,MS Sql和其他一些“。如果您只有一种数据库类型,那么依靠测试驱动程序会更容易一些,但您永远不知道未来版本的驱动程序会发生什么变化。对数据库名称中使用的每个输入进行统一检查仍然是最安全的选择。 –

+0

只有Microsoft SQL Server。 Java代码的安装与多个SQL Server数据库进行对话,但它们始终在同一个SQL Server实例/服务器上。 – Brandon

+0

从您的调用语句的语法中思考如此。不过,从“我无法获得当前版本的驱动程序以允许sql注入”转移到“没有任何人可以将sql注入到我的调用语句中,无论如何使用当前驱动程序版本或未来版本“将不允许字符串中的任何字符在数据库名称中无效,因此驱动程序无法正确解释。将字符串截断到一定长度也可能会有所帮助。 –