web-dev-qa-db-fra.com

Comment prévenir l'injection SQL avec JPA et Hibernate?

Je développe une application utilisant Hibernate. Lorsque je tente de créer une page de connexion, le problème de Sql Injection se pose . J'ai le code suivant:

@Component
@Transactional(propagation = Propagation.SUPPORTS)
public class LoginInfoDAOImpl implements LoginInfoDAO{

@Autowired
private SessionFactory sessionFactory;      
@Override
public LoginInfo getLoginInfo(String userName,String password){
    List<LoginInfo> loginList = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName='"+userName+"' and password='"+password+"'").list();
    if(loginList!=null )
        return loginList.get(0);
    else return null;   
          }
      }

Comment éviter l'injection SQL dans ce scénario? La syntaxe de création de table de la table loginInfo est la suivante:

create table login_info
  (user_name varchar(16) not null primary key,
  pass_Word varchar(16) not null); 
19
Mr. Singthoi
Query q = sessionFactory.getCurrentSession().createQuery("from LoginInfo where userName = :name");
q.setParameter("name", userName);
List<LoginInfo> loginList = q.list();

Vous avez d’autres options aussi, voyez ce Nice article de.

22
Petr Mensik

Vous devez utiliser des paramètres nommés pour éviter les injections SQL. De plus (rien à voir avec l'injection SQL mais avec la sécurité en général) ne renvoie pas le premier résultat mais utilise getSingleResult donc s'il y a plus d'un résultat pour une raison quelconque, la requête échouera avec NonUniqueResultException et connexion ne sera pas réussie

 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();
17
dimcookies

Qu'est-ce que l'injection SQL?

L'injection SQL se produit lorsqu'un attaquant non autorisé peut manipuler la requête processus de construction afin qu’il puisse exécuter une instruction SQL différente de celle de ce que le développeur de l'application a prévu à l'origine

Comment prévenir l'attaque par injection SQL

La solution est très simple et directe. Vous devez juste vous assurer que vous utilisez toujours les paramètres de liaison:

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

Maintenant, si certains essaient de pirater cette requête:

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

l'attaque par injection SQL sera empêchée:

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) ))]

Injection JPQL

L'injection SQL peut également se produire lors de l'utilisation de requêtes JPQL ou HQL, comme le montre l'exemple suivant:

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 requête JPQL ci-dessus n’utilise pas de paramètres de liaison, elle est donc vulnérable à l’injection SQL.

Découvrez ce qui se passe lorsque j'exécute cette requête JPQL comme ceci:

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

Hibernate exécute la requête SQL suivante:

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:[()]

Requêtes dynamiques

Vous devriez éviter les requêtes qui utilisent la concaténation de chaînes pour construire la requête de manière dynamique:

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

Si vous souhaitez utiliser des requêtes dynamiques, vous devez utiliser l'API des critères à la place:

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 (requête) .getResultList ();

Pour plus de détails, consultez cet article .

3
Vlad Mihalcea

Nous devrions toujours essayer d’utiliser des procédures stockées en général pour empêcher l’injection SQL. Si les procédures stockées ne sont pas possibles; nous devrions essayer de préparer des déclarations.

0
Deepak
  1. Paramètre de position dans HQL

    Requête hqlQuery = session.createQuery ("à partir d'ordres en tant qu'ordres où orders.id =?");

    Résultats de la liste = hqlQuery.setString (0, "123-ADB-567-QTWYTFDL"). List ();

  2. paramètre nommé en HQL

    Requête hqlQuery = session.createQuery ("de Employees as emp where emp.incentive>: incentive");

    Résultats de la liste = hqlQuery.setLong ("incentive", new Long (10000)). List ();

  3. liste de paramètres nommés dans HQL

    Liste des éléments = new ArrayList (); items.add ("livre"); items.add ("horloge"); items.add ("encre");

    Liste des résultats = session.createQuery ("de Cart en tant que panier où cart.item in (: itemList)"). SetParameterList ("itemList", items) .list ();

  4. JavaBean en HQL

Requête hqlQuery = session.createQuery ("à partir de livres en tant que livres où book.name =: name et book.author =: author");

Résultats de la liste = hqlQuery.setProperties (javaBean) .list ();

  1. Native-SQL

Requête sqlQuery = session.createSQLQuery ("Select * from Books where author =?");

Résultats de la liste = sqlQuery.setString (0, "Charles Dickens"). List ();

0
Neeraj Gahlawat