mybatis sql injection 취약점

 

Notice : 해당 자료가 저작권등에 의해서 문제가 있다면 바로 삭제하겠습니다.
연구목적으로 사용하지 않고 악의적인 목적으로 이용할 경우 발생할 수 있는 법적은 책임은 모두 본인에게 있습니다.

참고 : ibatis (ibatis.apache.org) 는 google code 쪽으로 이전했으며, 이름을 mybatis.org으로 바꿨다

1. myBatis 개요
mybatis_flow

MyBatis 는 Data Mapper 프레임워크로서, SQL을 XML으로 관리하며, 예외처리 및 트렌젝션 처리를 편리하게 할수 있도록 지원하는 Persistence Layer 프레임워크이다.

MyBatis 는 데이터베이스 레코드에 원시타입과 Map 인터페이스, 자바 POJO를 XML과 어노테이션으로 설정하고 매핑할 수 있는 단순하면서도 강력한 프레임워크이다.

2. myBatis 동작방식

아래의 예제는 mybatis의 동작방식을 설명하기 위해 작성된 소스이므로 프레임워크(Spring)와 연동하지 않고 구현하였다.
DB는 mysql을 사용하였으며, 스키마는 mybatis에서 샘플로 제공하는 jpetstore의 DB스키마 중 item테이블을 사용하였다. (참고 : http://mybatis.github.com/spring/sample.html)
예제 코드 위치 : https://github.com/apollo8900/mybatis_sample/

먼저 소스트리를 보면 아래와 같다.
src_tree

먼저 SqlSessionFactoryManager.java를 살펴보면,

SqlSessionFactoryManager 클래스에서 SqlMapConfig.xml 파일을 로딩(17번)하여 SqlSessionFactory 인스터스를 싱글톤으로 생성하도록 구현한다.
이렇게 생성된 SqlSessionFactory 인스턴스는 나중에 ItemDao 에서 사용될 것이다.

그러면 SqlMapConfig.xml 를 보자.

SqlMapConfig.xml에서는 db.properties파일을 읽어서(6번) Data Source 으로 JDBC Connection Pool을 생성(11번)한다.
그리고 mybatis에서 사용할 sql mapper 파일를 설정(20번)한다.

db.properties 파일에는 DB접속을 위한 정보를 작성한다.

이번에는 sql mapper이 설정된 item.xml 파일을 살펴보자.

mapper의 namespace를 mybatis_sample으로 설정하고 각각의 sql 을 작성한다.

여기서는 mybatis의 # 파라미터와 $ 파라미터의 취약점 테스트를 위해서 각각 2가지 sql 구문을 작성하였다.

getItems은 취약점이 없는 # 방식으로 파라미터를 받았고, getItems2는 취약점이 존재하는 $ 방식으로 파라미터를 받았다.

두가지 방식 모두 프로그램이 정상적으로 동작한다.

이번에는 실제 DB에 접속해서 sql을 처리하는 ItemDao.java를 보자.

ItemDao는 SqlSessionFactoryManager의 getSqlSessionFactory을 통해 인스턴스를 sqlMapper에 저장(12번)한다.

그리고 sqlMapper을 사용해서 세션을 열고 sql mapper에서 설정한 sql에 map 정보를 파라미터로 질의(19,24,29,34,39번)한다.

자, 그러면, 마지막으로 화면인 index.jsp를 살펴보자

먼저 itemDao의 인스턴스를 생성(7번)한다

keyword라는 파라마터를 입력(10번)받는다.
보안을 위해서는 keyword 입력값을 검증해야 하지만, 여기서는 mybatis 취약점 테스트를 위해서 입력값 검증을 하지 않는다.
keyword가 있으면, keyword 정보를 HashMap에 담아 getItems를 호출하고, 결과를 list에 담는다.
keyword가 없으면, getItemAll를 호출하고, 결과를 list에 담는다.

받은 list 정보를 JSTL(JSP Standard Tag Library)를 사용해서 보여준다.(54번)
view

3. myBatis 취약점 확인.

그러면 위에서 작성한 예제코드 활용하여 취약점 공격를 시도해 보겠다.(sqlmap 사용)

먼저 # 파라미터를 사용한 취약하지 않은 페이지를 공격 (item.xml의 getItems의 경우)

보는것과 같이 취약하지 않다.

위와 같이 공격이 들어올 경우 mybatis에서 동작하는 방식을 보면 아래와 같다..

위에서 보는것과 같이 # 파라미터를 prepareStatement으로 변환하여 파라미터를 매핑해주는 구조이다.

그러면, $ 파라미터를 사용한 취약한 페이지를 공격해보자 (item.xml의 getItems2의 경우)

위의 결과와 같이 sql injection를 통해 db의 정보를 알아올 수 있다.

이 경우 mybatis에서 동작하는 방식을 보면 아래와 같다..

prepareStatement 방식이 아닌, 단순히 $ 파라미터 자리에 String 변수가 replace 되고 있는 것을 확인할수 있다. (에러도 많이 발생하고 있다.)

4. 대응방안

– 입력값을 반드시 검증후 사용
– $ 파라미터 대신 # 파라미터를 사용.

참고 :
https://code.google.com/p/mybatis/wiki/Welcome?tm=6
http://mybatis.github.com/mybatis-3/ko/index.html
http://mybatis.github.com/spring/sample.html)
https://github.com/apollo8900/mybatis_sample/

 

This entry was posted in Java/JSP, Security/Hacking and tagged , , , . Bookmark the permalink.

댓글 남기기