Saltar al contenido

¿Cómo prevenir la inyección de SQL con JPA e Hibernate?

Solución:

Query q = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName = :name");
q.setParameter("name", userName);
List<LoginInfo> loginList = q.list();

También tienes otras opciones, mira este bonito artículo de mkyong.

Debe utilizar parámetros con nombre para evitar la inyección de SQL. Además (nada que ver con la inyección SQL pero con la seguridad en general) no devuelva el primer resultado pero use getSingleResult por lo que si hay más de un resultado por alguna razón, la consulta fallará con NonUniqueResultException y el inicio de sesión no será exitoso

 Query query= sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName=:userName  and password= :password");
 query.setParameter("username", userName);
 query.setParameter("password", password);
 LoginInfo loginList = (LoginInfo)query.getSingleResult();

¿Qué es la inyección SQL?

La inyección de SQL ocurre cuando un atacante deshonesto puede manipular el proceso de construcción de consultas para poder ejecutar una declaración SQL diferente a la que el desarrollador de la aplicación pretendía originalmente.

Cómo prevenir el ataque de inyección SQL

La solución es muy simple y directa. Solo debes asegurarte de usar siempre los parámetros de vinculación:

public PostComment getPostCommentByReview(String review) {
    return doInJPA(entityManager -> {
        return entityManager.createQuery(
            "select p " +
            "from PostComment p " +
            "where p.review = :review", PostComment.class)
        .setParameter("review", review)
        .getSingleResult();
    });
}

Ahora, si alguien está intentando piratear esta consulta:

getPostCommentByReview("1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) )");

se evitará el ataque de inyección SQL:

Time:1, Query:["select postcommen0_.id as id1_1_, postcommen0_.post_id as post_id3_1_, postcommen0_.review as review2_1_ from post_comment postcommen0_ where postcommen0_.review=?"], Params:[(1 AND 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ))]

Inyección JPQL

La inyección de SQL también puede ocurrir cuando se utilizan consultas JPQL o HQL, como se demuestra en el siguiente ejemplo:

public List<Post> getPostsByTitle(String title) {
    return doInJPA(entityManager -> {
        return entityManager.createQuery(
            "select p " +
            "from Post p " +
            "where" +
            "   p.title="" + title + """, Post.class)
        .getResultList();
    });
}

La consulta JPQL anterior no usa parámetros de vinculación, por lo que es vulnerable a la inyección de SQL.

Vea lo que sucede cuando ejecuto esta consulta JPQL como esta:

List<Post> posts = getPostsByTitle(
    "High-Performance Java Persistence' and " +
    "FUNCTION('1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ) --',) is '"
);

Hibernate ejecuta la siguiente consulta SQL:

Time:10003, QuerySize:1, BatchSize:0, Query:["select p.id as id1_0_, p.title as title2_0_ from post p where p.title="High-Performance Java Persistence" and 1 >= ALL ( SELECT 1 FROM pg_locks, pg_sleep(10) ) --()=''"], Params:[()]

Consultas dinámicas

Debe evitar las consultas que utilizan la concatenación de cadenas para crear la consulta de forma dinámica:

String hql = " select e.id as id,function('getActiveUser') as name from " + domainClass.getName() + " e ";
Query query=session.createQuery(hql);
return query.list();

Si desea utilizar consultas dinámicas, debe utilizar Criteria API en su lugar:

Class<Post> entityClass = Post.class;
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<?> root = query.from(entityClass);
query.select(
    cb.tuple(
        root.get("id"),
        cb.function("now", Date.class)
    )
);


return entityManager.createQuery(query).getResultList();
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *