Java Spring JPA原生查询是否防注入?

13

我写这个问题是因为我没有找到任何有关如何在Spring Data JPA中预防SQL注入的有用文章。所有的教程都展示了如何使用这些查询,但它们没有提及这些可能的攻击。

我有以下查询:

@Repository
public interface UserRepository extends CrudRepository<User, Integer> {

    @Query(nativeQuery = true, value = "SELECT * FROM users WHERE email LIKE %:emailAddress%")
    public ResponseList<User> getUsers(@Param("emailAddress") String emailAddress);
}

Rest控制器用于传递请求:

@RequestMapping(value = "/get-users", method = RequestMethod.POST)
public Response<StringResponse> getUsers(WebRequest request) {
    return userService.getUsers(request.getParameter("email"));
}

在执行JPQL或本地查询参数之前,它们是否被转义?

以下是在我的MySQL控制台中执行SQL注入并删除用户表的查询:

SELECT * FROM users WHERE email LIKE '%'; DROP TABLE users; -- %';

我尝试通过向服务器发送POST请求来执行SQL攻击:

http://localhost:8080/get-users
POST: key/value: "email" : "'; DROP TABLE users; --"

我已启用了Hibernate的SQL日志记录,以下是该请求生成的内容:

[http-nio-8080-exec-8] DEBUG org.hibernate.SQL - SELECT * FROM users WHERE email LIKE ?
Hibernate: SELECT * FROM users WHERE email LIKE ?

[http-nio-8080-exec-8] DEBUG org.hibernate.loader.Loader - bindNamedParameters() %'; DROP TABLE users; -- % -> emailAddress [1]
[http-nio-8080-exec-8] TRACE o.h.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [%'; DROP TABLE users; -- %]

表格没有被删除(这是好的),但为什么参数没有被转义?

如果我不注释@Param("emailAddress"),而是使用索引参数,会怎样呢?

@Query(nativeQuery = true, value = "SELECT * FROM users WHERE email LIKE ?1")
public ResponseList<User> getUsers(String email);

2
使用like %:emailAddress%like ?1like %?1%like ?1%like %?1都不会发生SQL注入。因为无论是名称参数还是位置参数,最终Hibernate都会生成本地SQL语句like ? - RJ.Hwang
1个回答

17

Spring Data JPA使用绑定参数来实现其所有功能。几乎没有发生字符串拼接,而且只有少量的字符串拼接是不来自于最终用户的。

因此,Spring Data JPA在防范SQL注入方面非常安全。

如果我不注解@Param("emailAddress")并且使用索引参数会怎样呢?

这与您使用索引参数还是命名参数无关。

为什么参数没有被转义?

因为绑定参数值不是SQL语句的一部分,也不会解析和转换成数据库中的执行计划,所以没有必要对参数进行转义。实际上这样做会是一个错误。


你能分享一下春季文档源代码的链接吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接