预编译语句是否能够避免 SQL 注入?

41

我已经阅读并尝试向我的应用程序注入易受攻击的SQL查询,但这样做不够安全。我只是使用Statement Connection对数据库进行验证和其他插入操作。

使用preparedStatements是否安全?此外,这个语句是否也存在问题?


1
准备好的语句是正确的选择。据我所知,准备好的语句只会被解析一次,因此以后不会发生SQL注入的情况。当然,您仍然需要对输入进行消毒以防止XSS攻击等。 - CurtainDog
4个回答

66

使用字符串拼接来构建查询语句并不会使 PreparedStatement 更加安全。看一下这个例子:

preparedStatement = "SELECT * FROM users WHERE name = '" + userName + "';";

如果有人输入:

' or '1'='1

作为userName,如果您使用PreparedStatement,那么您的查询将容易受到SQL注入攻击,因为该查询将在数据库中执行。

SELECT * FROM users WHERE name = '' OR '1'='1';

因此,如果您使用

preparedStatement = "SELECT * FROM users WHERE name = ?";
preparedStatement.setString(1, userName);

你会安全的。

这段代码部分取自维基百科上的文章。


10
setString会有什么差别?它实际上是做什么的?即使它将直接替换字符串,那又有何不同之处呢? - Mohamed Saligh
23
@Mohamed说:“这很重要。查询"SELECT * FROM users WHERE name = ?"将被发送到数据库,编译后setString中的userName将被替换。如果数据库看到非法值,它将抛出错误。因此,' or '1'='1将被视为整个字符串,而不是涉及运算符or=的语句。数据库将其视为带有值"' or '1'='1"的字符串。” - darioo

2

如果正确使用,预处理语句可以保护免受SQL注入攻击。但是,请在您的问题中发布一个代码示例,以便我们可以查看您是否正确使用它。


1

PreparedStatement单独使用并不能帮助您,如果您仍在拼接字符串。

例如,一个恶意攻击者仍然可以执行以下操作:

  • 调用休眠函数,使所有数据库连接都忙碌,从而使您的应用程序不可用
  • 从数据库中提取敏感数据
  • 绕过用户身份验证

这不仅仅是SQL受到影响。即使是JPQL也可能会被破坏,如果您没有使用绑定参数。

底线是,在构建SQL语句时永远不要使用字符串拼接。使用专门的API来完成此任务:


1

仅仅使用PreparedStatement并不能保证您的安全。您必须在SQL查询中使用参数,这是通过PreparedStatement实现的。请查看此处以获取更多信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接