【问题标题】:Is a SQL Injection Possible using a Java PreparedStatement and a MySQL Stored Routine是否可以使用 Java PreparedStatement 和 MySQL 存储例程进行 SQL 注入
【发布时间】:2012-10-21 17:38:28
【问题描述】:

Java:

PreparedStatement stmt = myConnection.prepareStatement("CALL myStoredRoutine(?, ?, ?)");
stmt.setString(1, a);
stmt.setString(2, b);
stmt.setString(3, c);
stmt.executeQuery();

如果我的存储例程在 MySQL 中,未过滤的字符串是否可以将某些内容注入我的代码中?

【问题讨论】:

  • 基本上没有。但是如果你的存储过程构建动态sql语句并执行它,它可能会变成一个可能的SQL注入。
  • 假设您有此查询SELECT * FROM userTable WHERE userName = ?。如果您使用的是preparedStatement,它会直接发送到编译它的数据库,然后setString() 方法中的userName 将被替换。如果它发现一个非法值,它将导致抛出异常。 userName like ' or '1'='1 将被视为一个完整的字符串,而不是涉及像 or= 这样的运算符的语句。因此,它是安全的。

标签: java mysql stored-procedures prepared-statement


【解决方案1】:

不,因为PreparedStatement 是为防止SQL Injection 而构建的。

我看到你正在调用一个存储过程,所以最好使用CallableStatement

String SQL = "{CALL myStoredRoutine(?, ?, ?)}";
CallableStatement cstmt = myConnection.prepareCall(SQL);
  • 准备好的声明

PreparedStatement 的实例包含已编译的 SQL 语句。这就是使声明“准备好”的原因

因为 PreparedStatement 对象是预编译的,所以它们的执行速度可以比 Statement 对象快。

prepared statement用于执行sql查询

  • 可调用语句

CallableStatement 对象提供了一种以标准方式为所有 RDBMS 调用存储过程的方法。存储过程存储在数据库中;对存储过程的调用是 CallableStatement 对象包含的内容。

【讨论】:

    【解决方案2】:

    不,这是不可能的。字符串准备好的语句过滤。实际上,这是他们的观点之一。

    【讨论】:

      【解决方案3】:

      没有。参数绑定的目的是将参数解析为参数。这对性能也有好处。

      【讨论】:

        【解决方案4】:

        当您使用参数化查询时,如果需要,参数会被解析并使用转义字符进行转换,因此不可能。这就是使用参数化查询/准备语句的优势。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-06
          • 1970-01-01
          • 2011-05-18
          • 1970-01-01
          • 1970-01-01
          • 2012-11-13
          相关资源
          最近更新 更多