java - 过滤应用程序服务器上执行的 SQL 查询

标签 java sql sql-server oracle sql-injection

首先,我知道这是不好的做法,但无论如何我仍在寻找答案。

在我们的 Web 应用程序中,我们有一个文本区域,用户可以在其中编写 SQL 来引入自定义数据集并在图表中查看它们。其工作方式本质上是获取写入的字符串并将其作为查询执行。我正在寻找的是我需要在应用程序服务器后端安全方面实现的一切,以禁止执行产生 SELECT 类型查询以外的结果的查询。

用户将无法执行他想要的任何类型的 SELECT 查询,因为应用服务器后端将返回的结果集扩展为包含 2 个名为 X_FIELD 的列,并且Y_FIELD 因此,我们并不担心用户能够查看数据,而是担心用户执行会破坏数据库的 SQL。

我们想做的是解析字符串中的关键字,例如 DROPALTERCREATE 等。我们是否有具体的事情有什么要注意的吗?有没有一个工具/库可以自动执行此操作?我们使用 java 作为后端代码。

最佳答案

过滤查询可以在应用程序级别完成,但与为每个数据库创建单独的安全系统相比,它需要更多的数据库特定专业知识。

作为示例,我创建了一个 open source program可以为 Oracle 做到这一点。它不会解决您的问题,但代码至少可以帮助解释为什么这是一个坏主意。

首先,了解 Oracle SQL 语法比大多数编程语言(例如 Java)复杂得多,这一点很重要。 Oracle有2175个关键字,几乎没有一个是保留的。忘记解析 SQL - 现有的第 3 方解析器都不够准确,无法安全地执行此操作。

幸运的是,此任务不需要完整的解析器。 Oracle 语法的结构方式使得任何语句都可以仅用 8 个标记进行分类,不包括 空格和注释。

但是建立一个 tokenizer和一个 statement classifier还是很难。该解决方案将处理 不常见的选择类型,例如 (select * from Dual)with asdf as (select 1 a from Dual) select a from asdf;。但即使是 SELECT 语句也可能导致 对数据库的更改;通过隐藏在函数或类型中的 PL/SQL,或者通过更新锁定行。

并且不要忘记删除(有时是可选的)terminator 。他们工作得很好 在大多数 IDE 中,但在动态 SQL 中不允许使用。不要只删除最后一个字符或最后一个标记,因为某些 SELECT 语句允许中间使用分号。

<小时/>

对于一个数据库而言,这就是一项艰巨的工作!如果您想使用此方法来实现安全策略,您需要几乎 100% 的准确性。很少有人对任何数据库有足够的狂热来构建这个。您不可能对多个数据库执行此操作。

关于java - 过滤应用程序服务器上执行的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32588285/

相关文章:

java - Bitmap 到 Byte[] 转换的更快方法

php - 使用 PHP 连接到列式数据库

mysql - 统计在接下来 7 天内同一日期预订的所有人数

sql - 为什么在 SQLite 中 `SELECT (SELECT 1 UNION SELECT 2 UNION SELECT 3) INTERSECT SELECT 3 UNION SELECT 4` 等于 4 而不是 3?

sql-server - 带有 XML 路径的函数不起作用

c# - 在 UTF16 列中存储 UTF8 数据

java - JPA - 运行测试用例时未启用编织

java - 使用 HttpURLConnection 发送 MultipartEntity

java - 与范围内的空日期进行比较

sql - JdbcTemplate动态表名和SQL注入(inject)