1

正如我们所知,避免 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 注入?

4

3 回答 3

1

第 1 行不会检查开发者是否想要删除表。如果您编写查询,则假定它没问题。

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

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

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

于 2013-04-23T06:46:05.497 回答
1

一个必须区分几个问题。

使用准备好的语句本身不会有任何帮助。
以及通常使用未准备好的方式没有害处。

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

术语“准备好的语句”意味着所有进入查询的动态数据使用占位符。所以,

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

所以,再一次 - 只有所有动态数据准备语句的占位符才有效。它之所以有效,是因为:

  • 每个动态值都必须正确格式化
  • 准备好的语句使正确的格式化(或处理)不可避免
  • 准备好的语句在唯一合适的地方进行正确的格式化(或处理)——就在查询执行之前,而不是其他地方,所以,我们的安全不会依赖于像这样不可靠的来源
    • 一些“魔术”功能,宁愿破坏数据也不愿使其安全。
    • 一个(或几个)程序员的好意,他们可以决定在程序流的某个地方格式化(或不格式化)我们的变量。这是非常重要的一点。
  • 准备好的语句影响进入查询的值,但不影响源变量,源变量保持不变,可以在进一步的代码中使用(通过电子邮件发送或显示在屏幕上)。
  • 准备好的语句可以显着缩短应用程序代码,在后台进行所有格式化(*仅在驱动程序允许的情况下)。
于 2013-04-23T06:50:31.157 回答
-1

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

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

于 2013-08-23T13:15:04.430 回答