Oracle数据库中的Java是否支持参数化的预处理语句,以便安全地执行TRUNCATE TABLE语句?

c6ubokkw  于 2023-10-16  发布在  Oracle
关注(0)|答案(2)|浏览(127)

我试图截断一个表使用Java与Oracle数据库。我的目标是在避免SQL注入漏洞的同时实现这一点。下面是我尝试过的代码:

String tableName = "employee";
String truncateQuery = "TRUNCATE TABLE ?";
try (PreparedStatement statement = connection.prepareStatement(truncateQuery)) {
    statement.setString(1, tableName);
    statement.executeUpdate();
}

然而,当我执行这段代码时,我遇到了一个“无效的表名”错误。我知道将表名直接连接到查询字符串(“TRUNCATE TABLE”+ tableName)可能会导致命令注入漏洞。
我还确认了表名是有效的,因为直接在数据库中执行“TRUNCATE TABLE employee”可以正常工作。
我的问题是:在这种情况下,是否有一种方法可以有效地使用查询参数,以避免SQL注入,同时使用Java中的预准备语句和Oracle数据库截断表?
我感谢任何关于如何安全地实现这一目标的指导或建议。

dhxwm5r4

dhxwm5r41#

我不懂Java。但是,由于涉及到Oracle数据库,并且如果您可以使用存储过程,则可以将表名传递给它,并让过程截断作为参数传递的表。
大概是这样的:

SQL> create or replace procedure p_trunc (par_table_name in varchar2) is
  2  begin
  3    execute immediate 'truncate table ' || dbms_assert.sql_object_name (par_table_name);
  4  end;
  5  /

Procedure created.

测试:

SQL> select * from test;

        ID
----------
         1
         2
         3

SQL> exec p_trunc('test');

PL/SQL procedure successfully completed.

SQL> select * from test;

no rows selected

SQL>

dbms_assert.sql_object_name
验证输入参数字符串是否为现有SQL对象的限定SQL标识符
这意味着它可以防止你担心的SQL注入。
如果您接受了这个建议,那么剩下的就是了解如何从Java程序调用存储过程; A帮不上忙。

ycggw6v2

ycggw6v22#

在这种情况下,是否有一种方法可以有效地使用查询参数,以避免SQL注入,同时使用Java中的预准备语句和Oracle数据库截断表?
不你不能这么做正如评论者所说,SQL表名(或列名、表达式等)不能参数化为PreparedStatment。只有值可以参数化。
AFAIK,对于所有其他数据库产品的JDBC驱动程序也是如此。
如何避免SQL注入和截断表?
您可以完全避免生成SQL字符串,并预先填充(比如说)一个Map来将用户提供的表名转换为每个(已知)表的TRUNCATE语句,这对于用户来说是安全的。
或者,您可以创建一个“安全截断”表的列表,并根据该列表验证用户提供的表名。然后为TRUNCATE生成SQL。
或者,您可以确保用户不能提供表名。
底线是,在PreparedStatement中参数化SQL表名只会给您给予错误的安全感。坏人仍然可以通过传递一个 * 不应该 * 被截断的表名来造成混乱。

相关问题