java

您所在的位置:网站首页 java转码防止sql注入 java

java

2024-05-21 15:52| 来源: 网络整理| 查看: 265

我有这样的代码。

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 注入(inject)攻击。

查询:我不确定表名如何用作准备语句(如本例中使用的name),这是100%的安全性针对 SQL 注入(inject)的措施。

谁能给我建议,解决这个问题的可能方法是什么?

注意:我们可以在未来迁移到 DB2,因此该解决方案应与 Oracle 和 DB2 兼容(如果可能,独立于数据库)。

最佳答案

有点遗憾的是,JDBC 不允许您将表名作为语句内的绑定(bind)变量。 (这是有原因的)。

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

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

并将TUSER绑定(bind)到语句的表名。

因此,唯一安全的方法是验证用户输入。不过,最安全的方法是不验证它并允许用户输入通过数据库,因为从安全的角度来看,您总是可以指望用户比您的验证更聪明。 永远不要相信在您的语句中连接的动态的、用户生成的字符串。

那么什么是安全验证模式?

模式 1:预构建安全查询

1) 在代码中一劳永逸地创建所有有效语句。

Map 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);

看看 unsafeUserContent 变量如何永远不会到达数据库。

3) 制定某种策略或单元测试,检查您所有的 statementByTableName 是否对您的模式有效,以供将来发展,并且没有表格丢失。

模式2:双重检查

您可以 1) 验证用户输入确实是一个表名,使用无注入(inject)查询(我在这里输入伪 sql 代码,您必须调整它才能使其工作,因为我没有 Oracle 实例实际检查它是否有效):

select * FROM (select schema_name || '.' || table_name as fullName FROM all_tables) WHERE fullName = ?

并在此处将您的全名绑定(bind)为准备好的语句变量。如果您有结果,那么它就是一个有效的表名。然后您可以使用此结果构建安全查询。

模式三

它有点介于 1 和 2 之间。 您创建一个名为“TABLES_ALLOWED_FOR_DELETION”的表,然后用适合删除的所有表静态填充它。

然后你让你的验证步骤成为

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

如果这有结果,那么你执行safe_table_name。为了额外的安全,标准应用程序用户不应写入此表。

不知何故我觉得第一种模式更好。

关于java - 语句有动态表名时如何防止SQL注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49171540/



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3