복붙노트

[SQL] 어떻게 JPA와 최대 절전 모드로 SQL 주입을 방지하기 위해?

SQL

어떻게 JPA와 최대 절전 모드로 SQL 주입을 방지하기 위해?

나는 최대 절전 모드를 사용하여 응용 프로그램을 개발하고있다. 나는 로그인 페이지를 만들려고 할 때, SQL 인젝션의 문제가 발생합니다.  나는 다음과 같은 코드가 있습니다 :

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

? 어떻게 다음과 같이 LOGININFO 테이블의 테이블 구문은 생성이 시나리오에서 SQL 주입을 방지 할 수 있습니다 :

create table login_info
  (user_name varchar(16) not null primary key,
  pass_word varchar(16) not null); 

해결법

  1. ==============================

    1.

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

    당신은 너무 다른 옵션이 mkyong에서이 좋은 문서를 참조하십시오.

  2. ==============================

    2.당신은 SQL 주입을 방지하기 위해 명명 된 매개 변수를 사용해야합니다. 또한 첫 번째 결과를 반환하지만 어떤 이유 하나 개 이상의 결과가 그렇다면 getSingleResult를 사용하지 않는 (아무것도 SQL 주입하지만, 일반적으로 보안 할 수 없습니다), 쿼리가 NonUniqueResultException에 실패하고 로그인이 성공적인되지 않습니다

    당신은 SQL 주입을 방지하기 위해 명명 된 매개 변수를 사용해야합니다. 또한 첫 번째 결과를 반환하지만 어떤 이유 하나 개 이상의 결과가 그렇다면 getSingleResult를 사용하지 않는 (아무것도 SQL 주입하지만, 일반적으로 보안 할 수 없습니다), 쿼리가 NonUniqueResultException에 실패하고 로그인이 성공적인되지 않습니다

     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();
    
  3. ==============================

    3.이 솔루션은 매우 간단하고 직선적이다. 당신은 당신이 항상 바인드 매개 변수를 사용하는 것이 확인해야합니다 :

    이 솔루션은 매우 간단하고 직선적이다. 당신은 당신이 항상 바인드 매개 변수를 사용하는 것이 확인해야합니다 :

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

    자,이 쿼리를 해킹하려고 일부가되는 경우 :

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

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

    JPQL 또는 HQL 쿼리를 사용할 때 다음의 예에 의해 입증으로 SQL 주입도 일어날 수있다 :

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

    이 SQL 인젝션에 취약하므로 JPQL 쿼리 위, 바인드 매개 변수를 사용하지 않습니다.

    나는이 같은이 JPQL 쿼리를 실행할 때 발생하는 체크 아웃 :

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

    Hibernate는 다음 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:[()]
    

    동적으로 쿼리를 작성하기 위해 문자열 연결을 사용하는 쿼리를 피해야한다 :

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

    동적 쿼리를 사용하려면, 대신 조건 API를 사용해야합니다 :

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

    반환 entityManager.createQuery (쿼리) .getResultList ();

    자세한 내용은이 문서를 확인하십시오.

  4. ==============================

    4.내가 검색처럼 쿼리의 사용 가능한 독특한 SQL 주입입니다 여기에 추가하고 싶습니다.

    내가 검색처럼 쿼리의 사용 가능한 독특한 SQL 주입입니다 여기에 추가하고 싶습니다.

    우리는 다음과 같이 우리가 쿼리 문자열 있다고 가정 해 봅시다 :

    queryString = queryString + " and c.name like :name";
    

    이름 매개 변수를 설정하는 동안, 대부분은 일반적으로 이것을 사용합니다.

    query.setParameter("name", "%" + name + "%");
    

    이제, "1 = 1"이 때문에 TypedQuery의 주입 할 수 없으며 최대 절전 모드는 기본적으로 처리합니다 같은 전통적인 매개 변수 위에서 언급 한 바와 같이.

    그러나 때문에 밑줄의 사용이다 LIKE 쿼리 구조의 여기 가능한 독특한 SQL 주입이있다

    이제, 우리의 시나리오의 경우 우리가 설정 한 경우

    등등.

    이상적인 수정 :

    ___ \ _ \ _ \ _ (3 개 당량 원료 밑줄)이 될 것이다

    마찬가지로, 그 반대의 쿼리는 %의 필요가 탈출 할 수있는 주사가 발생합니다.

  5. ==============================

    5.우리는 항상 저장 프로 시저가 불가능 SQL 인젝션 .. 경우에 방지하기 위해 일반적으로 저장 프로 시저를 사용하려고한다 우리는 문 준비를 위해 시도해야합니다.

    우리는 항상 저장 프로 시저가 불가능 SQL 인젝션 .. 경우에 방지하기 위해 일반적으로 저장 프로 시저를 사용하려고한다 우리는 문 준비를 위해 시도해야합니다.

  6. from https://stackoverflow.com/questions/14102334/how-to-prevent-sql-injection-with-jpa-and-hibernate by cc-by-sa and MIT license