java - 使用准备好的语句进行 SQL 注入(inject)而不使用绑定(bind)变量?

标签 java sql sql-injection

众所周知,避免 SQL 注入(inject)的最佳方法是使用带有绑定(bind)变量的预准备语句。但我有个问题是什么 如果我只使用准备好的语句,但不绑定(bind)如下所示的变量,其中客户 ID 来自用户界面

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

即使我没有使用绑定(bind)变量,第 1 行也会注意限制 sql 注入(inject)吗?

我同意最好的方法是下面的,但如果上面的方法也能处理限制sql注入(inject),那么我更喜欢上面的方法(如 它是一个遗留项目)

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

不使用绑定(bind)变量的准备语句是否足以确保不可能进行 SQL 注入(inject)?

最佳答案

一个人必须区分几个问题。

仅使用准备好的语句本身不会有任何帮助。
一般来说,使用非准备的方式也没有什么坏处。

只有当您需要将动态部分插入查询时,该功能才起作用。 因此,在后一种情况下,这样的动态部分必须仅通过占位符进入查询,而实际值必须稍后绑定(bind)(占位符是 ? 或表示查询中实际数据的任何其他标记)。

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

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

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

  • 每个动态值都必须格式正确
  • 准备好的语句使得正确的格式(或处理)不可避免
  • 准备好的语句在唯一正确的位置进行正确的格式化(或处理) - 就在查询执行之前,而不是其他地方,因此,我们的安全不会依赖于此类不可靠的来源,例如
    • 一些“神奇”功能,它宁愿破坏数据而不是保证数据安全。
    • 一个(或多个)程序员的良好意愿,他们可以决定在程序流中的某个位置格式化(或不格式化)我们的变量。这是非常重要的一点。
  • 准备好的语句会影响进入查询的值,但不会影响源变量,源变量保持不变并可在进一步的代码中使用(通过电子邮件发送或在屏幕上显示)。
  • 准备好的语句可以使应用程序代码大大缩短,在幕后完成所有格式化(*仅在驱动程序允许的情况下)。

关于java - 使用准备好的语句进行 SQL 注入(inject)而不使用绑定(bind)变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16162526/

相关文章:

Mac、Windows 和 Linux 上的 Java 桌面应用程序安装程序

java - 在 Asynctask 中显示 Progresscircle

Java char[] array jPasswordField处理和SQL更新语句

mysql - 此 Ruby on Rails 代码是否容易受到 SQL 注入(inject)攻击?

SQL Server 数据库注入(inject)

sql - SQL 注入(inject)中的双连字符/破折号。它们是用来做什么的?

Java - 无需图形的准确字体高度

java - Neo4j DB - 客户端连接

mysql - 单个查询对数据进行分组

SQL Select 使用 Pivot 或 CASE 组合输出表中的行值