0. 주제 선정
SQL Injection에 대해 공부하는데 방어 기법으로 addslashes()와 mysql_real_escape_string()이 등장하였습니다. 그런데 책에서는 이 두가지 함수로 SQL Injection을 모두 방어할 수 있는 것처럼 나와있었습니다. 하지만 해킹이 어떤 분야입니까? 막으면 뚫는 분야 아닙니까!?
그래서 과연 이 두 함수라면 SQL Injection을 모두 막을 수 있는지? 우회할 수 있다면 어떤 식으로 우회가 가능한지 알아보고자 이 주제를 발표 주제로 선정하였습니다.
1. addslashes()와 mysql_real_escape_string()
(1) addslashes()란?
- 데이터베이스 질의 등에서 처리할 필요가 있는 문자 앞에 백슬래시를 붙인 문자열을 반환한다.
- 처리할 필요가 있는 문자 = 겉따옴표('), 겹따옴표("), 백슬래시(\), NUL(NULL 바이트)
- 예를 들어 don't 를 데이터베이스에 넣으려고 할 때 ' 앞에 \를 붙여서 don\'t 이 저장되는 겁니다. 이를 다시 웹에서 보여줄 때는 ' 앞에 있는 \가 없어져야하기 때문에 이때는 백슬래쉬를 제거해주는 stripslashes() 함수를 사용하는 겁니다.
- magic_quotes_gpc는 기본값으로 on이 되어있는 설정으로, 자동적으로 모든 GET, POST, COOKIE 데이터에 addslashes()를 실행합니다. 따라서 magic_quoties_gpc가 설정되어있을 때에는 addslashes()를 사용하지 마세요. 그렇게 되면 \가 두번 붙으니까요.
(2) mysql_real_escape_string()이란?
- 간단히 말해 위에서 다룬 addslashes()의 확장(?) 버전이라고 생각하시면 편합니다. 기능은 모두 동일하고 처리하는 문자가 더 많아집니다.
- 처리하는 문자 = \x00, \n, \r, \r, \, ', ", \x1a
- \x1a는 EOF(End Of a File)를 뜻합니다. ( CTRL+Z 기능)
2. SQL Injection 방어
비박스의 실습을 이용하여 진행해보도록 하겠습니다.
먼저 아무런 보안 조치가 되어있지 않은 경우입니다. 이 때는 항상 참이 되는 문장과 or을 하여 모든 데이터가 출력되도록 하였습니다.
해당 php 소스코드입니다. security_level에 따라 보안조치가 다른데 위에서 본 경우는 security_level이 0인 경우였습니다.
다음으로 1과 2가 있는데 1은 sqli_check_1으로, 2의 경우는 sqli_check_2의 함수로 보안조치를 한 것을 볼 수 있습니다. 해당 함수들의 기능을 찾아봅시다.
해당 함수들의 기능입니다. 간단하게 한줄로 구현되어있죠.
security_level이 1인 경우일 때 설정한 sqli_check_1 함수는 addslashes() 함수로 보안조치를 하였습니다.
다음으로 security_level이 2인 경우일 때 설정한 sqli_check_2 함수는 mysql_real_escape_string() 함수로 보안조치를 한 것을 볼 수 있습니다.
정말 SQL Injection이 되지 않는지 실제로 공격을 해보면 이와 같이 공격이 통하지 않는 것을 볼 수 있습니다.
책에서는 SQL Injection의 대응방안이라면서 해당 두 함수를 알려주고는 끝을 냈습니다. 저는 이 함수들을 우회하는 것은 없는지 알아보았습니다.
3. 대응방안 우회하기
찾아본 결과 특정 조건 하에서는 우회가 가능했습니다. 그것은 바로 멀티바이트를 사용하는 언어로 인코딩을 할 때입니다.
멀티바이트를 사용하는 언어셋 환경에서는 백슬래시 앞에 %a1~%fe의 값이 들어오면 해당 값과 \에 해당하는 %5c가 합쳐져서 하나의 문자를 나타내게 됩니다. 따라서 SQL Injection 방어를 위해 생성한 \가 사라져 버려서 공격이 되는거죠.
이것을 실제로 실습해보겠습니다. (출처 : http://dydgh499.tistory.com/32)
PHP 코드를 이와 같이 작성하였습니다.
GET 방식을 통해 입력받은 것을 mysql_real_escape_string을 거쳐 before에 출력시키고 이것을 mb_convert_encoding 함수를 통해 인코딩을 하고나서 after에 출력시키는 것으로 구현하였습니다.
* mb_convert_encoding 함수 = 인코딩해주는 함수
- string mb_convert_encoding(string $str, string $to_encoding, [$from_encoding])
ex) mb_convert_encoding($input, "UTF-8", "EUC-KR") = $input 문자열을 EUC-KR에서 UTF-8로 인코딩
입력창에 겉따옴표( ' )을 입력해보았습니다.
그 결과 mysql_real_escape_string 함수를 지나 ' 앞에 백슬래시(\)가 붙은 것을 볼 수 있습니다.
이 때 input 변수 앞에 %f1을 넣게 되면 결과적으로 %f1%5c%27 이 되고 멀티바이트 언어셋인 UTF-8에서는 %f1%5c를 하나의 문자로 보게 되어 이 둘을 하나로 묶고 %27만을 남겨둡니다.
따라서 after 부분을 보게 되면 백슬래시가 사라지고 '가 남아있는 것을 볼 수 있습니다. 이를 통해 공격자는 '를 사용할 수 있게 되고 이를 이용하여 SQL Injection 공격이 가능하게 되는 것입니다.
참고 )
http://dydgh499.tistory.com/32
'Hacking > Web' 카테고리의 다른 글
매직해시(Magic Hashes) 취약점 (0) | 2017.02.16 |
---|---|
A3. 크로스 사이트 스크립팅 (0) | 2017.02.09 |
A1-injection (0) | 2017.02.01 |
해킹맛보기 웹 해킹 파트 정리 (0) | 2017.01.08 |
구글 고급 연산자 (0) | 2017.01.08 |