从SQL注入中防止此语句

时间:2014-06-17 14:58:52

标签: java sql jdbc prepared-statement sql-injection

我正在尝试使用PreparedStatement类编写一个非常简单的查询。我在这里读到:Fail to convert to internal representation JDBC你不能参数化列名,只能参数化值。由于我的查询非常简单,唯一的价值是'我可以参数化count (*)

这是查询: SELECT COUNT (*) FROM EZ_DAY

如果我尝试像这样参数化: SELECT ? FROM EZ_DAY

我收到错误: Fail to convert to internal representationgetInt()上使用ResultSet方法时。

如何使用PreparedStatement并参数化此查询中的某些内容以防止SQL注入?另外我知道你不能参数化列名,这包括表名吗?例如,我可以这样做:

SELECT COUNT (*) FROM ?

2 个答案:

答案 0 :(得分:4)

该查询不能归入SQL注入。属于此类别的查询是您通过纯字符串连接构建的查询。例如:

String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = " + stringParameter;
Statement stmt = con.createStatement(query);
ResultSet rs = stmt.executeQuery();

在您的情况下,没有要注入的参数,因此无法针对您的特定情况进行SQL注入攻击。

如果您需要防止SQL注入攻击,请使用PreparedStatement并且不要连接查询。而是通过接口传递参数,这将为您转义任何无效字符:

String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = ?";
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, stringParameter);
ResultSet rs = pstmt.executeQuery();

如果您需要构建动态查询,那么无论是使用纯字符串连接还是StringBuilder

,您都可以重新使用连接字符串。
//Common solution, still suffers from SQL injection
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE 1 = 1 ";
if (stringParameter != null) {
    query = query + = "AND colX = " + stringParameter;
}

相反,最好对参数使用COALESCEIFNULL函数以避免出现这种情况:

//Better solution
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = COALESCE(?, colx)";

在上面的案例中:

  • 如果参数的值不同于null,则查询将如下所示:

    String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = ?";
    
  • 如果参数的值为null,则查询将如下所示:

    String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = colx";
    

在上一个示例中,您仍然可以使用PreparedStatement并避免SQL注入攻击。

相关:

答案 1 :(得分:0)

this post中所述,SQL注入可能导致非常严重的问题,如:

它不仅仅是可以受到影响的SQL。如果你没有使用绑定参数,甚至可以破坏JPQL。

最重要的是,在构建SQL语句时,不应该使用字符串连接。为此目的使用专用API: