【问题标题】:Does the preparedStatement avoid SQL injection? [duplicate]PreparedStatement 是否避免 SQL 注入? [复制]
【发布时间】:2011-05-18 23:53:04
【问题描述】:

我已阅读并尝试将易受攻击的 sql 查询注入我的应用程序。它不够安全。我只是将语句连接用于数据库验证和其他插入操作。

preparedStatements 安全吗?而且这个说法也会有问题吗?

【问题讨论】:

  • 准备好的陈述是要走的路。 AFAIK 准备好的语句只会被解析一次,因此以后不会有 SQL 注入的机会。当然,您仍然需要清理输入以防止 XSS 攻击等。

标签: java jdbc prepared-statement sql-injection


【解决方案1】:

使用字符串连接从任意输入构造查询不会使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);

你会安全的。

部分代码取自this Wikipedia article

【讨论】:

  • setString 有什么不同吗?它实际上是做什么的?即使那将替换字符串就地。它有什么不同?
  • @Mohamed:这很重要。查询"SELECT * FROM users WHERE name = ?" 将被发送到编译它的数据库,然后来自setStringuserName 将被替换。如果数据库看到非法值,它将抛出错误。因此,' or '1'='1 将被视为整个字符串,而不是涉及运算符 or= 的语句。数据库会将其视为值为 "' or '1'='1" 的字符串。
【解决方案2】:

如果使用得当,准备好的语句确实可以防止 SQL 注入。但是请在您的问题中发布代码示例,以便我们查看您是否正确使用它。

【讨论】:

    【解决方案3】:

    简单地使用PreparedStatement 并不能保证您的安全。您必须在SQL 查询中使用参数,这可以通过PreparedStatement 实现。更多信息请查看here

    【讨论】:

      【解决方案4】:

      如果您仍在连接字符串,单独的 PreparedStatement 对您没有帮助。

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

      • 调用 sleep 函数,使您的所有数据库连接都处于忙碌状态,从而使您的应用程序不可用
      • 从数据库中提取敏感数据
      • bypassing the user authentication

      不仅 SQL 会受到影响。如果不使用绑定参数,甚至 JPQL 也会受到影响。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-16
        • 2017-12-02
        • 2011-09-15
        • 2015-11-30
        • 2014-05-30
        • 1970-01-01
        • 2015-01-06
        • 1970-01-01
        相关资源
        最近更新 更多