본문 바로가기
Web Technologies 🖥️/spring

[mybatis] - ' #{} '이랑 ' ${} ' 똑같은 거 아니였어?

by dudefromkorea 2023. 11. 17.

오늘은 mybatis 에서 혼동되기 쉬운

 #{} ${} 에 대해서 이야기해 보도록 하겠습니다

 

 

mybatis 란?

Java 를 위한 오픈 소스 SQL 매핑 프레임워크

 

SQL Query 의 실행 결과를 Java 객체와 맵핑하는 기능을 제공하고

조건에 따라 SQL 문을 동적으로도 생성할 수 있는 기능을 제공하며

SQL 을 Java 코드와 분리하여 XML 파일이나 어노테이션을 통해 관리한다

 

따라서, 개발자 입장에서 SQL 문을 쉽게 작성하고 관리할 수 있고

JDBC 로 처리되는 상세한 작업들을 추상화기에

SQL 관리를 직관적으로 만들며 유지보수 측면에서도 효율적이다

(Query 실행, 결과 매핑, 트랜잭션 관리 등등)

 

 

'#{}' (Parameter Binding)

PreparedStatement 의 바인딩 방식과 유사하다

(PreparedStatement 에 대한 설명 보러 가기)

 

Query 가 실행되기 전 mybatis 는

#{} 를 해당 파라미터의 값으로 대체하고

JDBC 의 '?' 플레이스홀더로 변환하여 직접 Query 에 포함시키지 않고

별도의 값으로 전달하기에 SQL Injection 에 대해서 안전하다

(SQL Injection 에 대한 설명 보러 가기)

 

'1' OR '1' = '1' 과 같은 입력을 하더라도, Query 에 직접 삽입되지 않고

이를 문자열 값 하나로 인식하고 처리하므로 쿼리의 논리를 변경할 수 없다

 

하지만 동적인 SQL 요소에는 적합하지 않다

(테이블 이름, 칼럼 이름 등등)

#{} 를 이용한 SQL Injection 예시

/** mapper */
SELECT * FROM user WHERE id = #{userId}

/** SQL */
SELECT * FROM user WHERE id = ?

/** SQL Injection Attempt */
SELECT * FROM user WHERE id = '1' OR '1'='1' /** SQL Injection fail */

 

 

 

'${}' (String Substitution)

문자열 치환을 통해 파라미터의 값을 Query 에 직접 삽입한다

 

mybatis 가 별도의 검증 과정을 거치지 않고

파라미터의 값이 Query 의 일부로 해석되기 때문에

SQL Injection 에 취약할 수 있다

 

'1' OR '1' = '1' 과 같은 입력 한다면, Query 에 직접 삽입되어

  원래 의도와 달리 쿼리의 논리가 변경될 수 있다

 

동적인 SQL 요소에 유용하지만

SQL Injection 방지를 위한 검증 단계가 별도로 필요하다

${} 를 이용한 SQL Injection 예시

/** mapper */
SELECT * FROM user WHERE id = '${userId}'

/** SQL */
SELECT * FROM user WHERE id = 'actualData'

/** SQL Injection Attempt */
SELECT * FROM user WHERE id = '1' OR '1'='1' /** SQL Injection success */
728x90
반응형