【问题标题】:Appscan source edition - SQL InjectionAppscan 源码版 - SQL 注入
【发布时间】:2015-09-26 09:47:15
【问题描述】:
我正在使用 Appscan 源代码版本进行 Java 安全编码。它在我的应用程序中报告 SQL 注入。问题是我们在代码中动态生成查询,所以我不能使用准备好的语句。相反,我必须使用Esapi.encoder().encodeForSql(new OracleCodec(), query)。 AppScan 不认为这可以缓解 SQL 注入问题。
final String s = "SELECT name FROM users WHERE id = " +
Esapi.encoder().encodeForSql(new OracleCodec(), userId);
statement = connection.prepareStatement(s);
此代码还不适用于ESAPI.encoder()
我该如何解决这个问题?
【问题讨论】:
标签:
java
sql-injection
owasp
esapi
secure-coding
【解决方案1】:
你应该做的是
final String s = "SELECT name FROM users WHERE id = ?"
statement = connection.prepareStatement(s);
statement.setString(1, userId);
【解决方案2】:
encodeForSQL 的文档推荐了一个 PreparedStatement,您仍然可以使用它来动态生成查询:
根据所选编解码器对输入进行编码以用于 SQL 查询
(适当的编解码器包括 MySQLCodec 和 OracleCodec)。 这个
不推荐方法。 PreparedStatement接口的使用
是首选方法。但是,如果由于某种原因这是
不可能,则提供此方法作为较弱的替代方法。
最好的方法是确保任何单引号都是双引号。
另一种可能的方法是使用中描述的 {escape} 语法
1.5.6 节中的 JDBC 规范。但是,这种语法不
与所有驱动程序一起工作,并且需要修改所有查询。
让我们检查一下编码器在做什么,看看为什么你的代码存在注入漏洞。编码器在 oracle 编解码器中调用 encodeCharacter,它只是将单引号替换为两个单引号:
public String encodeCharacter( char[] immune, Character c ) {
if ( c.charValue() == '\'' )
return "\'\'";
return ""+c;
}
仅当值在单引号内时才有意义,即字符串值。如果id 实际上是一个整数,并且您想将它与查询连接起来,那么您应该先将其转换为 int 类型,而不是使用此编码器。