当前位置: 首页 > 知识库问答 >
问题:

当语句具有动态表名时,如何防止SQL注入?

易炳
2023-03-14
   final PreparedStatement stmt = connection
                .prepareStatement("delete from " + fullTableName
                    + " where name= ?");
   stmt.setString(1, addressName);

fulltableName的计算类似于:

 public String getFullTableName(final String table) {
    if (this.schemaDB != null) {
        return this.schemaDB + "." + table;
    }
    return table;
 }

这里的schemadb是环境的名称(可以随时间改变),table是表名(将固定)。

schemadb的值来自xml文件,该文件使得查询容易受到SQL注入的攻击。

有没有人可以建议我,有什么可能的方法来处理这件事?

注意:我们将来可以迁移到DB2,因此该解决方案应该与Oracle和DB2兼容(如果可能的话,应该与数据库无关)。

共有1个答案

邵毅
2023-03-14

不幸的是,JDBC不允许您将表名作为语句中的绑定变量。(这是有其原因的)。

所以你可以不写,或者实现这种功能:

connection.prepareStatement("SELECT * FROM ? where id=?", "TUSERS", 123);

并将tuser绑定到语句的表名。

1)用代码一次性地创建所有有效语句。

Map<String, String> statementByTableName = new HashMap<>();
statementByTableName.put("table_1", "DELETE FROM table_1 where name= ?");
statementByTableName.put("table_2", "DELETE FROM table_2 where name= ?");

如果需要,可以使用select*from all_tables;语句使创建本身动态化。all_tables将返回SQL用户有权访问的所有表,您还可以从中获取表名和模式名。

2)选择映射中的语句

String unsafeUserContent = ...
String safeStatement = statementByTableName.get(usafeUserContent);
conn.prepareStatement(safeStatement, name);
select * FROM 
    (select schema_name || '.' || table_name as fullName FROM all_tables)
WHERE fullName = ?

这是一种介于1和2之间的混合。创建一个名为“TABLES_ALLOWED_FOR_DELETION”的表,然后静态地填充所有适合删除的表。

则使验证步骤为

conn.prepareStatement(SELECT safe_table_name FROM TABLES_ALLOWED_FOR_DELETION WHERE table_name = ?", unsafeDynamicString);

如果有结果,则执行safe_table_name。为了额外的安全,这个表不应该是标准应用程序用户可写的。

 类似资料:
  • 我正在使用jdbc PreparedStatement进行数据插入。 tablename和columnString是动态生成的。 我尝试过参数化tablename和columnString,但它们只会解析为类似'tablename'这样的东西,这将违反语法。

  • 问题内容: 我与一个声誉很高的PHP专家进行了讨论: PDO在这里没有用。以及mysql_real_escape_string。质量极差。 这当然很酷,但是老实说我不知道​​建议使用or PDO修复此代码有什么问题: 入这个 ,考虑到JavaScript代码已发送到客户端。 问题答案: 您的建议确实不正确。 不适用于动态表名;它旨在转义仅 由引号分隔的字符串数据 。它不会逃脱反引号字符。这是一个很

  • 问题内容: 我想动态过滤JDBI查询。 参数列表是通过REST从UI传递的,例如 这是(笨拙地)构建(Jersey @Context UriInfo :: getQueryParameters-> StringBuilder)的,类似于以下内容: 并传递给JDBI,它看起来像这样: 据我了解,当前的实现容易受到SQL注入的攻击。我显然可以清除列名,但不能清除值。1个 必须有一种更优雅且SQL注入证

  • 问题内容: 停止使用不推荐使用的mysql_ *函数后,我切换到mysqli。但是后来,我注意到未准备好的语句对于SQL注入是不安全的。然后,我再次更改了代码。 我所拥有的是以下函数,该函数检查数据库中是否存在变量 $ ID 并打印该行的 title 值: 我将其更改为: 我的问题是:这是执行准备好的语句的正确方法吗?另外,我现在可以安全使用SQL注入吗?非常感谢任何愿意回答这个问题的人:) 问题

  • 问题内容: 准备好的语句如何帮助我们防止SQL注入攻击? 维基百科说: 准备好的语句可以抵御SQL注入,因为稍后需要使用其他协议传输的参数值不需要正确地转义。如果原始语句模板不是从外部输入派生的,则不会发生SQL注入。 我不太清楚原因。用简单的英语和一些例子,简单的解释是什么? 问题答案: 这个想法很简单-查询和数据被发送到数据库服务器 分开 。 就这样。 SQL注入问题的根源在于 代码和数据 的

  • 问题内容: 我正在尝试执行这样的mysql查询 它显示这样的错误 我该如何实现? 问题答案: 在查询中动态表名的使用最好与 Prepared Staments一起使用 ,在mysql中也可以使用串联功能 您也可以针对删除查询执行此操作