准备语句如何比语句更好地防止SQL注入?

时间:2014-03-10 20:38:23

标签: java mysql sql jdbc prepared-statement

后台:我已经开始使用JDBC和MYSQL模拟书店,所有本地项目。为了连接到数据库,我开始使用Statement,但我开始读到,当多次使用查询只更改其参数时,为这些查询使用PreparedStatement会更有效。但是,我最常阅读的优点是PreparedStatements如何更好地防止SQL注入。

来源: 这个帖子的答案here
谷歌
教授

我的问题: 在处理参数化查询时,PreparedStatements如何更好地阻止SQL注入,甚至不同于语句?我很困惑,因为如果我理解正确,值仍然会被传递到执行的SQL语句中,这只取决于程序员清理输入。

3 个答案:

答案 0 :(得分:6)

可以自己完成所有的卫生设施,这是对的,因此注射安全。但这更容易出错,因此不太安全。换句话说,自己动手可能会导致更多可能导致注入漏洞的错误。

一个问题是转义规则可能因数据库而异。例如,标准SQL只允许使用单引号('foo')中的字符串文字,因此您的卫生设施可能只会逃避那些;但MySQL允许双引号("foo")中的字符串文字,如果你不对它们进行清理,如果你使用MySQL,你将会受到注入攻击。

如果使用PreparedStatement,则该接口的实现由相应的JDBC Driver提供,而实现负责转义您的输入。这意味着清理代码是由编写JDBC驱动程序的人编写的,这些人可能知道数据库特定的转义规则的来龙去脉。他们也很可能比你测试手动逃逸功能更彻底地测试那些逃避规则。

因此,如果您编写preparedStatement.setString(1, name),该方法的实现(同样,由您正在使用的数据库的JDBC驱动程序人员编写)可能大致如下:

public void setString(int idx, String value) {
    String sanitized = ourPrivateSanitizeMethod(value);
    internalSetString(idx, value);
}

(请记住,上面的代码是草图;许多JDBC驱动程序实际上处理它的方式完全不同,但原理基本相同。)

另一个问题是,myUserInputVar是否已被消毒可能并不明显。请看以下代码段:

private void updateUser(int name, String id) throws SQLException {
    myStat.executeUpdate("UPDATE user SET name=" + name + " WHERE id=" + id);
}

这样安全吗?您不知道,因为代码中没有任何内容表明name是否已被清理。而且你不能只是重新消毒“保持安全”,因为这会改变输入(例如,hello ' world将成为hello '' world)。另一方面,准备好的UPDATE user SET name=? WHERE id=?语句总是安全的,因为PreparedStatement的实现会在将值插入?之前转义输入。

答案 1 :(得分:1)

当使用PreparedStatement的方式时 - 使用带有参数占位符的固定查询文本,没有外部值的连接 - 那么就可以防止SQL注入。

这种保护大致有两种方式:

  1. JDBC驱动程序正确转义值并将它们插入占位符位置的查询中,并将完成的查询发送到服务器(AFAIK只有MySQL Connector / J执行此操作,并且只能使用useServerPrepStmts=false这是默认值。

  2. JDBC驱动程序将查询文本(带占位符)发送到服务器,服务器准备查询并发回参数的描述(例如类型和长度)。然后,JDBC驱动程序收集参数值,并将这些参数值作为参数值块发送到服务器。然后,服务器使用这些参数值执行准备好的查询。

  3. 考虑到服务器准备和执行查询的方式,此时不能进行SQL注入(除非您执行存储过程,并且该存储过程通过连接动态创建查询)。

答案 2 :(得分:0)

框架,Sql驱动程序确保转义输入。如果使用字符串语句并正确转义 - 将获得相同的结果。但不推荐这样做,因为Preparend语句似乎更多代码行,但也导致更多结构化代码。而不是长sql线汤。

另外,因为我们单独设置每个参数并且显式地根据所使用的数据库,底层驱动程序类可以正确地转义它们。这意味着您可以通过配置更改数据库,但无论驱动程序是否负责转义。因此,一个数据库可能需要转义斜线而另一个数据库可能需要两个单引号...

这也会导致代码减少,因为您不需要为此烦恼。简单地说,让应用程序代码下面的框架/公共类处理它。