Java Spring JPA 原生查询 SQL 注入证明吗?



我写这个问题是因为我没有找到任何关于如何在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);
}

用于传递请求的其余控制器:

@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);

Spring Data JPA对其所有功能都使用绑定参数。几乎没有字符串连接正在进行,并且只有不是来自最终用户的东西。

因此,Spring Data JPA对SQL注入是安全的。

如果我不批注@Param("电子邮件地址"(并且使用索引参数怎么办?

这与使用索引参数或命名参数无关。

为什么参数没有转义?

由于绑定参数值不是在数据库中解析并转换为执行计划的 SQL 语句的一部分,因此无需转义参数。事实上,这样做是错误的。

最新更新