본문 바로가기

해킹-보안

Mybatis $와 # 차이

반응형


마이바티스(MyBatis)를 사용하면 mapper 쿼리문이 담긴 XML 파일을 다루게 된다.
이때 달러($) 기호 또는 샾(#) 기호를 이용하여 쿼리문을 작성할 때 파라미터 값을 설정한다.
각 기호는 용도가 다르기 때문에 구분해서 사용해야 한다.


# {}


#을 사용한 쿼리문이다.
 <select id="select_list" parameterType="HashMap" resultType="HashMap">
     SELECT    USER_NAME
             ,       USER_ID
     FROM     USER
     WHERE   USER_ID     = #{USER_ID}
            AND USER_PW  = #{USER_PW}
 </select>

#{}이 사용된 쿼리문이 실행되면 아래처럼 쿼리문에 ?가 생긴다.

 <select id="select_list" parameterType="HashMap" resultType="HashMap">
     SELECT    USER_NAME
             ,       USER_ID
     FROM     USER
     WHERE   USER_ID     = ?
            AND USER_PW  = ?
 </select>

sql 문장에 정해지지 않은 값을 물음표(?)로 표시하며 그 뒤에 바인딩 변수를 지정한다.
그리고 파라미터가 String으로 변환된다. 
예를들어 위 SQL의 경우 #{USER_ID} 값이 test 라면 쿼리문에는 USER_ID = 'test'의 형태로 바뀐다. 
즉, #을 사용하면 ?에 파라미터가 바인딩되어 수행된다. 
변수에 홑따옴표(‘)도 자동으로 붙여 쿼리가 수행되므로 '#{USER_ID}' 처럼 쿼리문을 작성하지 않아도 된다. 
이 방식은 SQL Injection을 예방할 수 있어 보안 측면에서 유리하다.



$ {}


$를 사용한 쿼리문이다.
 <select id="userTable" parameterType="Map" resultType="">
     SELECT
         *
     FROM
         user
     WHERE
         id = '${id}' AND password = '${password}'
 </select>

$는 String.concat 함수처럼 동작하여 파라미터가 바로 출력되고 해당 컬럼의 자료형에 맞추어 파라미터 자료형이 변경된다.
#과 달리 $는 자동으로 홑따옴표(‘)가 붙지 않아서 아래처럼 테이블명 혹은 컬럼명을 동적으로 결정하거나 정렬을 할 때 사용할 수 있다. 

 <select id="select" resultType="String" parameterType="Map">
     SELECT
         name AS name
     FROM
         user_${id}
     WHERE
         id = #{id}
 </select>

만약 ${id}가 아닌 #{id}로 수행된다면 user_'id' 형태로 실행되어 에러가 발생된다.
파라미터 값이 변경될 때 마다 쿼리문 파싱을 하여 성능에 영향을 주고 SQL 쿼리문에 사용되는 문법을 제대로 필터링 하지 

않는 경우 SQL Injection 공격에 취약할 수 있다. 


아래와 같은 로그인 매퍼가 대표적인 예시이다.





로그인 아이디 폼에 admin '--로 로그인 수행 시 USERPASS가 주석으로 처리되어 패스워드를 인증하지 않는다.


그러나 아래와 같이 개행을 하면 주석을 이용한 인젝션은 수행되지 않는다.



 

mabatis에 적은 SQL은 내부적으로 JDBC 코드로 변환된다.
개행 여부에 따라 JDBC code로 변환된다면 두 결과는 같아야 하겠지만 다르다면 JDBC code 역시 다른 것으로 봐야한다.
추정상 mybatis는 JDBC code로 SQL mapper를 해석 할 때 불필요한 주석을 한 줄마다 제거 했을 가능성이 있다.
mybatis는 ${} 사용시에는 반드시 파라미터를 사전에 replace 등을 이용해서 SQL 공격을 방어하도록 string을 변형해야한다.
 


반응형