用没有绑定变量的预处理语句进行Sql注入?

时间:2013-04-23 06:33:32

标签: java sql sql-injection

我们知道避免sql注入的最佳方法是使用带有绑定变量的预处理语句。但我有疑问是什么 如果我只使用预备语句但不绑定变量,如下面的客户ID来自用户界面

String query ="select * from customer where customerId="+customerId;
PreparedStatement stmt = con.prepareStatement(query); //line1

即使我没有使用绑定变量,第1行是否会注意限制sql注入?

我同意下面最好的方法,但如果上面的方法也负责重写sql注入,那么我更喜欢上面的一个(如 它是一个遗产项目)

String query ="select * from customer where customerId=?";
  PreparedStatement stmt = con.prepareStatement(query); 
  stmt.setInt(1, 100);

是否准备好语句而不使用足够的绑定变量来确保不能进行sql注入?

3 个答案:

答案 0 :(得分:1)

第1行不会检查develeper是否想要删除表。如果您编写查询,则认为它是好的。

sql注入的目标是准备值,允许在没有开发人员的情况下进行额外的sql查询。使用属性中的假值来查询您的网站。 例如:

        id = "'); DROP ALL TABLES; --";
        query = "select * from customer where customerId="+id;

PreparedStatement确保使用setInt / setString / etc添加到查询中的特殊符号(如'或')不会干扰sql查询。

答案 1 :(得分:1)

必须区分几个问题。

使用预备声明本身不会有任何帮助。
一般而言,使用非准备方式也没有坏处。

只有在您需要将动态部分插入查询时才会有效。 因此,在后一种情况下,这样的动态部分必须进入查询仅通过占位符,实际值必须在以后绑定(占位符是?或任何其他代表查询中的实际数据)。

术语“预备声明”暗示使用占位符 所有进入查询的动态数据。所以,

  • 如果查询中没有动态部分,即使没有使用准备好的语句,也显然根本没有注入。
  • 如果您正在使用预准备语句,但是将值直接注入查询而不是绑定它们 - 那么注入就会很开放。

因此,再次 - 只有所有动态数据准备语句的占位符才有效。它起作用的原因是:

  • 每个动态值都必须格式正确
  • 预备语句可以正确格式化(或处理)不可避免的
  • 预备语句在正确的位置正确格式化(或处理) - 在查询执行之前,而不是在其他地方,因此,我们的安全不会依赖于像这样不可靠的来源
    • 一些'魔术'功能,它会破坏数据而不是安全。
    • 一个(或几个)程序员的善意,他们可以决定在程序流程的某个地方格式化(或不格式化)我们的变量。这是非常重要的一点。
  • prepared语句影响查询的非常值,但不会影响源变量,源变量保持不变,可以在其他代码中使用(通过电子邮件发送或在屏幕上显示)。
  • 预备语句可以使应用程序代码显着缩短,在幕后进行所有格式化(*仅在驱动程序允许的情况下)。

答案 2 :(得分:-1)

我知道这是一篇较旧的帖子,我只是想补充一点,如果你能确保只允许整数进入第1行的查询,就可以避免注入攻击。字符串输入是注入攻击发生的地方。在上面的示例中,不清楚哪个类变量'customerId',尽管它看起来像一个int。由于这个问题被标记为Java,你不能用int进行注入攻击,所以你应该没问题。

如果它是第1行中的字符串,则需要确信'customerId'来自一个必须是整数的安全源。如果它来自帖子表单或其他用户生成的字段,那么您可以尝试将其转义或将其转换为整数以确定。如果是字符串,则将其强制转换为整数,并且不需要绑定参数。