SQL 即使在准备好的语句上也可以注入

Is SQL injection possible even on a prepared statement

我在 Stack Overflow 上阅读了很多关于如何使用准备好的语句

来防止 SQL 注入的文章

但是有什么方法可以在准备好的语句上进行 SQL 注入还是 100% 安全?

下面是我的java代码

 String query = "SELECT * FROM Users WHERE username=? and password=?";

 ps=con.prepareStatement(query);  

 ps.setString(1,username);
 ps.setString(2,password);

 rs = ps.executeQuery();

 status = rs.next();

 if(status==true){
.....
}else{
....
}

我尝试了一些 sql 注入查询,例如

一些输入:

SELECT * FROM users WHERE username = 'xxx@xxx.xxx' OR 1 = 1 LIMIT 1 -- ' ] AND password = md5('1234');

SELECT * FROM users WHERE email = 'xxx@xxx.xxx' AND password = md5('xxx') OR 1 = 1 -- ]');

我也尝试了一些更多的查询,但是由于 SQL 注入查询的(单引号)'被转义(/')none 似乎有效。

如果上面的代码中有任何 SQL 注入 queries/techniques 可用于执行 SQL 注入,请建议我。

这个查询:String query = "SELECT * FROM Users WHERE username=? and password=?"; 是安全的,因为无论参数是什么,它仍然会作为一个简单的 select 执行。顶多浏览完一整个table.

但是准备好的语句只是一个工具,(糟糕的)程序员可能仍然会滥用它。

我们来看下面的查询

String query = "SELECT id, " + paramName + " FROM Users WHERE username=? and password=?";

其中 paramName 是参数名称。它仅与 paramName 一样安全,因为您直接使用变量来构建将由数据库引擎解析的字符串。这里 PreparedStatement 无能为力,因为 JDBC 不允许参数化列名。

所以这里的规则是:

  • 如果可以,请避免这种构造!
  • 如果您真的需要它,请仔细检查(正则表达式、允许的字符串列表等)paramName 不能是您期望的任何内容,因为 控制是唯一的预防措施 反对 SQL 注入