오늘은 이제까지 진행한 개발물에 대한 미니 발표회가 있었던 날이다. 다른 팀의 발표를 듣던 도중 알아보면 좋을 만한 주제가 있었다.
다른 팀 중에 Query DSL에 대해 알아보던 중 JPQL보다 Query DSL의 보안이 좋아서 사용했다라는 말이 있었다.
- Query DSL이 SQL Injection에 안전하다라고 하셨다.
이제까지 나는 Query DSL을 동적 쿼리를 처리하기 위해 사용했었다. Query DSL이 Type Safety가 있어서 런타임 시점이 아닌 컴파일 시점에 오류를 잡아준다는 점을 알고 있었지만, 보안이 더 뛰어나다라는 점에 대해서는 잘 알지 못해서 이점에 대해 알아보고자 한다.
우선 Query DSL은 정적 타입을 사용해 SQL 같은 쿼리를 생성할 수 있도록 하는 오픈소스 프레임워크이다.
- 메소드 체이닝 방식으로 쿼리를 작성하기 때문에 타입 체크를 받을 수 있다.
- Query DSL은 엔티티 클래스를 기반으로 Q도메인 클래스를 생성한다.
그럼 왜 Query DSL이 SQL Injection에 안전할까?
먼저 SQL Injection에 대해 알아보자.
SQL Injection
SQL 인젝션은 공격자가 입력 필드나 URL 매개변수를 통해 악의적인 SQL 코드를 주입하여, 데이터베이스를 임의로 조회하거나 조작하는 공격이다.
가장 대표적인 SQL 문으로는 다음과 같다. (예전에 보안 공부할 때.. 생각난다..)
1 | SELECT * FROM users WHERE username = 'admin' AND password = '' OR '1'='1'; | cs |
이렇게 ' OR '1'='1 를 넣으면, 인증이 우회되고, 전체 데이터베이스가 노출될 수 있다.
그럼! 여기서 SQL Injection을 방지하기 위해서는 어떻게 해야할까?
SQL Injection 대응 방법
SQL Injection을 방지하려면 Prepared Statement 또는 파라미터화된 쿼리를 사용해야 한다.
- 사용자가 입력한 값을 쿼리에 직접 삽입하지 않고, 바인딩하는 기술
- Prepared Statement는 데이터베이스에 미리 컴파일된 SQL 쿼리를 전송한 후, 필요한 값을 런타임에 바인딩하여 실행하는 방식이다.
- 파라미터화된 쿼리는 데이터베이스 드라이브가 입력값을 Escape 처리하거나 Prepared Statement 방식으로 변환하여 실행한다.
1 2 3 4 5 | String query = "SELECT * FROM users WHERE username = ? AND password = ?"; PreparedStatement pstmt = connection.prepareStatement(query); pstmt.setString(1, username); pstmt.setString(2, password); ResultSet rs = pstmt.executeQuery(); | cs |
?는 플레이스홀더 역할을 한다. 실제 값은 이후 코드에서 런타임 시 바인딩된다. 이 과정에서 데이터베이스 드라이버는 입력값을 SQL 문법과 분리하여 처리한다.
JPQL도 위와 같은 파라미터 바인딩을 사용하면 SQL Injection을 방지할 수 있다고 한다. 하지만, 아래와 같이 문자열을 직접 조합한 코드는 안전하지 않다고 한다.
1 2 3 | String jpql = "SELECT u FROM User u WHERE u.username = '" + username + "'"; Query query = entityManager.createQuery(jpql); query.getResultList(); | cs |
하지만, QueryDSL은 입력값을 자동으로 Prepared Statement의 파라미터로 변환하여 SQL Injection을 방지한다고 한다.
그럼 한가지 생각이 들 수 있다.
모든 쿼리에 파라미터화 하지 못할 수 있는데 그 경우는 어떻게 방지하는가?
현실적으로 생각해보면, 파라미터화된 쿼리를 적용하지 못하는 경우도 있을 것이다. (동적으로 테이블명을 정해야 한다던지..)
따라서, 이럴 때는 입력값 검증, 화이트리스트 기반 필터링, WAF ... 등등 의 방법이 있다고 한다.
항상 드는 생각이지만, 뭐든 트레이드 오프는 있는 것 같다. 따라서, 각각의 기술들의 장단점을 항상 비교해보며 선택을 하는 과정을 통해 내 주관과 기준을 세워나가야겠다.
'💻 개발 > 주문 플랫폼' 카테고리의 다른 글
11/18 - TIL : 1차 프로젝트 마무리 (0) | 2024.11.18 |
---|---|
11/16 - TIL : 좋은 테스트 코드 (1) | 2024.11.16 |
11/15 - TIL : userDetails에 null이 들어오는 문제 (0) | 2024.11.15 |
11/14 - TIL : POSTMAN 로그인 설정하기 (0) | 2024.11.14 |
11/13 - TIL - Sub Query와 Join (2) | 2024.11.13 |