在查询几乎完全可配置时限制SQL注入

时间:2017-10-16 13:24:22

标签: java sql prepared-statement mariadb sql-injection

我需要从Web应用程序执行SQL查询的计划转储。最初它是一个完整的表(只有表名是可配置的),但随后又添加了一个可配置的WHERE子句以及一列列。

现在需要的可配置选项是:

  • 表名称
  • where clause

此时,它可能只是整个查询,对吧?!

我知道SQLI可以通过java.sql.PreparedStatement稍微减轻,但据我所知,这依赖于在编译时知道列和数据类型。

可配置项目会向最终用户公开。它们将位于WEB-INF/classes内的属性文件中,因此我在这里进行辩护的用户是系统管理员,这些系统管理员并不像他们认为的那样好。

我在这里过于谨慎吗?

如果没有别的,如果WHERE子句是java.sql.PreparedStatementRobert'); DROP TABLE students;--可以阻止执行多个查询吗?

3 个答案:

答案 0 :(得分:0)

“一切都取决于”。

如果您有一个应用程序,用户可以在其中输入where子句作为自由文本,那么是的,他们可以构造SQL注入攻击。他们还可以通过选择巨大的笛卡尔连接来使服务器停止运行。

您可以创建一个可视化查询构建器 - 使用模式元数据显示表列表,并在选择表后为列,并为每列进行有效比较。然后,您可以将查询构造为参数化查询,并将人工输入限制为比较值,您可以将其用作参数。

这是一项很多工作,但在大多数生产系统中,让用户运行这种查询通常不是特别有用......

答案 1 :(得分:0)

准备好的声明不会为您处理此事。使用预准备语句,您只能安全地将参数添加到查询中,而不是表名,列名或整个where子句。

特别是后者如果没有任何限制,几乎不可能防止注射。可以根据静态定义的有效值列表或基于数据库结构动态地检查列和表名称参数。你可以对where参数进行一些基本的正则表达式检查,但这只会对明显的SQL注入有所帮助。 有了灵活性,你打算以SELECT FROM WHERE的形式提供这样的查询:

SELECT mycolumn FROM mytable WHERE id = 1 AND 'username' in (SELECT username FROM users) 

您可以查看类似JOOQ的内容,以提供安全的动态查询构建,同时仍然能够限制您的用户可以查询的内容。 以这种或那种方式约束您的用户是关键。不这样做意味着您不仅要担心SQL注入,还要担心例如性能问题。例如,为它们提供可视(拖放)查询构建器。

答案 2 :(得分:0)

允许用户执行任意查询是不安全的。这是你在Equifax看到的那种东西。你不想允许它。

准备好的声明无助于使SQL表达式安全。在预准备语句中使用参数有助于使安全。您只能在通常放置常量值的位置使用参数,例如数字,带引号的字符串或引用日期。

最简单的解决方案是不允许按需提供任意查询或表达。

相反,允许用户提交自定义查询以供审核。

查询由 审核,可以授权用户(或其他用户)运行存储的查询。如果您认为自己可以开发某种自动验证器,请成为我的客人,但恕我直言,除了让合格的数据库管理员对其进行审核之外,其他工作肯定要多得多。

随后,允许用户按需运行存储的查询,但仅限于其id。

以下是另一种选择:想要运行自定义查询的用户可以申请获取数据库的副本,以便在自己的计算机上托管。他们将获得他们有权查看的数据子集的转储。然后,如果他们运行查询废弃数据或融化他们的计算机,那就是他们的业务。