Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Java Spring JPA native query SQL injection proof?

I'm writing this question because I didn't find any useful article about how to prevent SQL Injection in Spring Data JPA. All the tutorials are showing how to use these queries but they don't mentioned anything about these possible attacks.

I'm having the following query:

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

The rest controller to deliver the request:

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

Are JPQL or native query parameters escaped before executing them?

This is the query with SQL injection executed in my MySQL console which drops the users table:

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

I have tried to execute the SQL attack by sending a POST request to the server:

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

I have enabled Hibernate's sql logging and this is what the above request produced:

[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; -- %]

The table wasn't dropped (which is good) but why the parameter isn't escaped?

What if I don't annotate the @Param("emailAddress") and I use indexed parameters?:

@Query(nativeQuery = true, value = "SELECT * FROM users WHERE email LIKE ?1")
public ResponseList<User> getUsers(String email);
like image 975
Zbarcea Christian Avatar asked Oct 13 '18 08:10

Zbarcea Christian


1 Answers

Spring Data JPA uses bind parameters for all its features. There is very little String concatenation going on and that only with stuff that doesn't come from end users.

Therefore Spring Data JPA is secure against SQL injection.

What if I don't annotate the @Param("emailAddress") and I use indexed parameters?

This is independent of you using indexed or named parameters.

why the parameter isn't escaped?

Since the bind parameter values are not part of the SQL statement that gets parsed and converted into an execution plan in the database there is no need to escape the parameters. Indeed it would be a mistake to do so.

like image 52
Jens Schauder Avatar answered Jan 03 '23 02:01

Jens Schauder