블로그 프로필 이미지




이스케이프 문자와 인젝션


 우리가 알고 있는 이스케이프 문자는 \(백슬래시) 로 시작되는 문자이며, 이스케이프는 PHP 나 기타 프로그래밍시 문자열에 대한 제어를 할 수 있는데 이러한 이스케이프 문자열중 자주 쓰이는 문자열은 \n(줄바꿈), \s(띄어쓰기)\t(들여쓰기-Tab), \\(백슬래시) 등이 있다.


 프로그래밍시 데이터베이스에서 쿼리의 값을 이스케이프시키는건 보안의 좋은 예 중 하나이다. 그 이유는 어렵게 생각할 필요는 없다. 만약 데이터베이스를 잘 모른다면 어렵게 다가올 수 있으나, 데이터베이스를 좀 다루어 본 사람이라면, 금방 알 수 있을것이다. 


 데이터데이스에서 쿼리를 통하여 검색삽입삭제업데이트 가 이루어지는데 이러한 데이터들을 PHP에서 처리한다면 기본적으로 큰 따옴표(") 와 작은 따옴표(') 안에서 작업이 이루어 질것이다. 하지만, 사용자의 입력으로부터 받아오는 값들은 100% 신뢰할 없기 때문에 항상 값들을 처리해야한다. 그이유는 데이터베이스 쿼리에 들어가는 값들이 악성 사용자에 의해 전혀 의도하지 않는 쿼리문을 생성시킬 수 있기 때문이다. 아래는 악성 사용자에 의해 이루어질 수 있는 데이터베이스 쿼리문중 가장 기본적인 예제이다.


 악성 사용자가 입력한 데이터 ( ' OR ''=' )



 서버에서 값을 처리할 시 


$query_string="SELECT *FROM member WHERE member_id='admin' AND member_pw='' OR ''=''";


 위의 예제는 악성 사용자가 관리자의 아이디를 알고 있을 시 이루어질 수 있는 악성행위 이다. 물론 위와 같이 비밀번호를 원문으로 사용하는곳은 없을것이다. 위의 예제에선 쉽게 보여주기위한 예제중 하나이다. 또한 이러한 방법 아닌 아이디입력 부분에서 admin' OR ''=' 값을 입력하여도 접속이 이루어 질 수 있다. 


 이러한 악성 사용자에 의해 이루어지는 데이터베이스 쿼리 공격을 인젝션 공격 이라고 한다. 이러한 인젝션 공격을 막기 위해선 앞쪽에서 설명한 이스케이프 문자를 이용하여야 한다.




데이터베이스 쿼리값을 이스케이프 시키기


 이곳에선 코드이그나이터를 설명하기 때문에 CI 에서 제공되는 데이터베이스 라이브러리를 이용하여 쿼리값을 이스케이프 시키는 방법을 알아보도록 하자. 우선 적으로 데이터베이스 라이브러리를 사용하기 위해선 아래와 같이 database 라이브러리를 로드해 주어야 한다.


$this->load->database();


 CI 에서는 쿼리값을 이스케이프 시키는 방법에 대해 두가지를 제공한다. 하나는 쿼리값을 이스케이프 시키는 함수를 사용하는 방법이며, 다른 하나는 바인딩 쿼리를 이용하여 쿼리값을 이스케이프 시키는 방법이다. 각각의 사용방법은 정말 간단하기 때문에, 길게 설명할 필요가 없는것같다. 아래는 각각의 사용방법에 대한 간단한 예제이다.


 쿼리 이스케이프 함수 사용하기


<?php
/* 문자열 */
$string="' OR ''='";

/* 이스케이프 함수 사용 */
$escape_str=$this->db->escape($string);

/* 출력 */
echo $escape_str;

/* 결과 => \' OR \'\'=\' */
?>


 바인딩 쿼리 사용하기


<?php
/* 입력된 아이디값 */
$id="admin' OR ''='";

/* 입력된 비밀번호값 */
$pw="' OR ''='";

/* 쿼리 문자열 : 쿼리값에 들어가는 값을 물음표(?) 로 넣어준다 */
$query_string="SELECT *FROM test WHERE test_id = ? AND test_pw = ?";

/* 쿼리 바인딩 사용 : 두번째 인수값을 배열형태로 차례대로 넣어준다 */
$query=$this->db->query($query_string,array($id,$pw));

/* 쿼리 바인 실행시 예상되는 쿼리 문자열
=> SELECT *FROM test WHERE test_id = 'admin\' OR \'\'=\'' AND test_pw = '\' OR \'\'=\''
*/
?>

   

 위와 같이 쿼리의 값을 이스케이프 시키는 방법에 대해 알아보았다. 여기서 중요한 점이 한가지 있는데 CI 에서는 쿼리값에 대한 이스케이프 함수가 자체적으로 작은 따옴표를 생성하기 때문에 쿼리문자열을 만들 시 작은 따옴표는 없애는게 좋다. 만약 아래와 같이 작은 따옴표를 사용하여 만들어진 쿼리문자열에 CI의 이스케이프 함수를 사용한다면 데이터베이스의 결과는 오류를 나타낼 것이다.


 CI 에서 이스케이프 함수 사용시 주의할 점


<?php
/* test 아이디 값 */
$test_id="admin";

/* 이스케이프 시키기 */
$test_id=$this->db->escape($test_id);

/* 쿼리 문자열 */
$query_string="SELECT *FROM test WHERE test_id='".$test_id."'";

/* 쿼리 실행 */
$query=$this->db->query($query_string);

/* 예상되는 결과의 쿼리 문자열 : 이스케이프 함수에 의해 작은 따옴표 두개가 입력되게 된다.
=> SELECT *FROM test WHERE test_id=''admin''
*/
?>





댓글
doodoori2 2015.12.28 13:30  Edit  Rep

좋은 글 감사합ㄴ디ㅏ.

CI에서 escape 함수를 따로 제공하긴 하지만,
ORM을 사용하는 경우 따로 escape를 안 해줘도 되니까
ORM 사용 방법도 함께 언급해 주시는 것이 CI를 공부하시는 분들에게 더 도움이 될 것 같습니다.

위와 같은 경우에는 아래와 같은 형태로 쓸 수 있겠네요

$query = $this->db->select('*')->from('test')->where('test_id', $test_id)->get();

Favicon of http://b.redinfo.co.kr Dreamload 2016.01.02 13:40 신고  Edit

좋은 답글 감사드립니다!
저같은 경우 CI 의 ORM 을 거의 사용하지 않기 때문에 ORM 부분을
생각하지 못하고 제외시켜버린것같네요 ㅎ
doodoori2 님 말씀데로 ORM 사용방법도 상세히 올려놓았다면,
더 좋은 글이 될 수 있었을것같네요 ㅎ
덕분에 배워갑니다~

(비회원은 자신의 글을 볼 수 없습니다.)