1

我正在使用 Appscan 源代码版本进行 Java 安全编码。它在我的应用程序中报告 SQL 注入。问题是我们在代码中动态生成查询,所以我不能使用准备好的语句。相反,我必须使用 e 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()

我该如何解决这个问题?

4

2 回答 2

1

你应该做的是

final String s = "SELECT name FROM users WHERE id = ?"
statement = connection.prepareStatement(s);
statement.setString(1, userId);
于 2015-08-15T08:46:59.070 回答
0

encodeForSQL的文档建议PreparedStatement您仍然可以使用动态生成的查询:

根据选定的编解码器(适当的编解码器包括 MySQLCodec 和 OracleCodec)对 SQL 查询中使用的输入进行编码。不推荐这种方法。使用 PreparedStatement 接口是首选方法。但是,如果由于某种原因这是不可能的,则提供此方法作为较弱的替代方法。最好的方法是确保任何单引号都是双引号。另一种可能的方法是使用 JDBC 规范 1.5.6 节中描述的 {escape} 语法。但是,此语法不适用于所有驱动程序,并且需要修改所有查询。

让我们检查一下编码器在做什么,看看为什么你的代码存在注入漏洞。编码器调用encodeCharacteroracle 编解码器,它简单地将单引号替换为两个单引号:

public String encodeCharacter( char[] immune, Character c ) {
    if ( c.charValue() == '\'' )
        return "\'\'";
    return ""+c;
}

仅当值在单引号内时才有意义,而字符串值将是。如果id实际上是一个整数,并且您想将它与查询连接起来,那么您将首先将其转换为 int 类型,而不是使用此编码器。

于 2015-08-15T10:01:17.087 回答