Dremio SQL注入漏洞

问题描述 投票:0回答:1

我想通过带有 Dremio 的 Spring Java 应用程序查询包含 parquet 文件的 S3 存储。这些是具有用户给定参数的动态查询。 我使用 Apache Arrow SQl 驱动程序,只需通过使用以下属性中的

JdbcTemplate
实例化的
DataSource
来运行查询:

  driver-class-name: org.apache.arrow.driver.jdbc.ArrowFlightJdbcDriver
  url: jdbc:arrow-flight-sql://localhost:32010/?useEncryption=false
  username: user
  password: pwd

对于 sql 字符串,我使用使用用户给定值格式化的字符串:

"SELECT * FROM "my-s3-storage".table t WHERE t.description = '%s';".formatted(userInput)

它运行良好,但不用说它有多大的 SQL 注入机会。如果我尝试使用 Prepared Statement:

String sql = "SELECT * FROM "my-s3-storage".table t WHERE t.description = ?"
jdbcTemplate.query(sql, ps -> ps.setString(1, userInput), rs -> {
  //handling the result set
});

我收到以下错误:

cfjd.org.apache.arrow.flight.FlightRuntimeException: Cannot convert RexNode to equivalent Dremio expression. RexNode Class: org.apache.calcite.rex.RexDynamicParam, RexNode Digest: ?0

我在网上发现了含糊不清的信息。在一些论坛上可以找到 Dremio 不支持准备好的语句的说法,但所有这些评论都有好几年了*,而且 Dremio 官方网站有一篇文章推荐使用准备好的语句..

据我所知,Dremio 在底层使用 ANSI SQL,我相信它支持准备好的语句。或者这取决于数据库引擎而不是方言?谁能确认 Dremio 仍然不可能?那我就不再继续追求了。

如果是这种情况,我将转义不安全字符,使用字典来编码和解码用户给定的字符等。 如果您有其他建议或经验来缓解没有准备好的语句的 SQL 注入,我也将不胜感激!

谢谢!

*我发现的最新更新:https://community.dremio.com/t/sql-parameterization-support/1733/5

jdbc sql-injection ansi-sql dremio apache-arrow-flight
1个回答
0
投票

我将发布我的发现作为答案,也许它对同一条船上的人有用:

由于缺乏任何其他想法,我走上了编码/解码之路。

最初的想法是使用自己的字典,但我认为十六进制编码应该足够了。 幸运的是,Dremio SQL 有一个

FROM_HEX
函数,它可以 返回给定十六进制字符串的 BINARY 值。

有了它,我(到目前为止..)可以安全地构建动态查询,将任何类型的用户给定输入转换为十六进制字符串,然后在执行时转换回来,该函数的行为有点像包装器。

尽管如此,这并不是一个完全平静的解决方案,但据我所知,目前确实没有更好的选择。我听说 Dremio 将实施准备好的声明(令人震惊的是他们还没有实施),在那之前,让我们期待最好的结果!

© www.soinside.com 2019 - 2024. All rights reserved.