防止JPQL查询sql注入

Posted

技术标签:

【中文标题】防止JPQL查询sql注入【英文标题】:Prevent JPQL query sql injection 【发布时间】:2019-07-30 05:21:24 【问题描述】:

我被告知以下查询不安全,因为来自前端输入字段的参数 :searchFor 可用于 SQL 注入。 请告知在以下代码中防止 SQL 注入的最佳解决方案是什么?

@Query("SELECT u FROM User u WHERE lower(u.username) LIKE %:searchFor% " +
        " OR lower(concat(u.firstname, ' ', u.lastname)) LIKE %:searchFor% " +
        " OR lower(u.email) LIKE %:searchFor%")
Page<User> findAllAndSearch(@Param(value = "searchFor") String searchFor, Pageable pageable);

我没有使用“+”来连接字符串,而是提供参数 (:searchFor)。不确定这是否仍然不安全。

【问题讨论】:

Are SQL injection attacks possible in JPA?的可能重复 【参考方案1】:

我相信,如果以这种方式作为参数传递,底层 ORM 框架会清理输入。

【讨论】:

【参考方案2】:

我被告知以下查询作为参数不安全:searchFor

你应该质疑这个建议。

当客户端传递的参数值可能会传输额外的查询逻辑(通常是不需要的)并且在执行的查询中是允许的时,就会发生 SQL 注入。 例如,除了 searchFor 的简单 foo 文本值之外,参数值还可以在查询中包含附加逻辑,例如:foo OR ''=''。那就是SQL注入。

在您的情况下,SQL 注入是不可能的,因为您没有手动设置参数,而是依靠一种安全的方式来绑定searchFor 参数:Spring。 实际上,Spring 像 JPA 实现一样以安全的方式绑定参数值,即从 JPA Query 实例设置参数值,该实例可防止声明参数的 SQL 注入。

以这个查询为例(我删除了% 部分以简化):

"SELECT u FROM User u WHERE lower(u.username) LIKE :searchFor"

并尝试使用字符串"foo OR ''==''" 设置searchFor 的参数,以尝试注入始终为真的SQL 条件。 如果您打开 JPA 实现的日志以输出参数绑定(对于 Hibernate:logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE),您可能会看到类似:

TRACE 11012 --- [nio-8080-exec-8] o.h.type.descriptor.sql.BasicBinder : 绑定参数 [1] 作为 [VARCHAR] - [foo OR ''=='']

为参数值执行绑定,而不是作为添加新查询逻辑的一种方式。受保护的最终查询部分的保护如下:

SELECT u FROM User u WHERE lower(u.username) LIKE "foo OR ''==''"

【讨论】:

以上是关于防止JPQL查询sql注入的主要内容,如果未能解决你的问题,请参考以下文章

如果应该准备所有 SQL 查询以防止 SQL 注入,为啥语法允许非准备查询?

模糊查询 防止 sql注入

怎么防止SQL注入?

mybatis如何防止sql注入

参数化查询防止Sql注入

参数化查询为什么能够防止SQL注入 (转)