我之所以写这个问题,是因为我没有找到关于如何防止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);
答案 0 :(得分:1)
Spring Data JPA对其所有功能都使用绑定参数。几乎没有String串联,只有那些不是来自最终用户的东西。
因此,Spring Data JPA可以防止SQL注入。
如果我不注释@Param(“ emailAddress”)而使用索引参数怎么办?
这与使用索引或命名参数的情况无关。
为什么不对参数进行转义?
由于绑定参数值不是要解析并转换为数据库中执行计划的SQL语句的一部分,因此无需转义参数。确实这样做是错误的。