SQL 인젝션?
그렇다. 대부분이 웹해킹을 하면 제일 많이듣는 기법중 5손가락안에는 드는 그것!
OWASP에도 거의 탑쓰리급으로 제일 먼저 나오는 그것!
SQL인젝션은 사용자가 입력한 값을 서버에서 검증하지 못하거나 안했을 때 데이터베이스가 쿼리를 정상인식해버려서 정보가 노출된다던가 공격자가 원하는 결과를 뽑게 만들어준다.
SQL 인젝션이 일어나는 쿼리를 예시를 들자면
select * from testtable where id='' or 1=1 #' AND password='';
가 되겠다.
실습하면서 보도록 하자.
실습(GET/Search)
실습페이지 이동, Search와 Select 두개중에 Search를 선택한다.
선택 시 나오는 첫 화면, 영화를 데이터베이스에서 검색해주는 기능을 한다.
처음으로 해야할 것은 '를 넣어서 SQL 인젝션 취약점이 있는지 확인한다.
Oops! 이렇게 에러메시지가 뜨게된다.
그러나 이러한 에러 메시지를 통해 공격자는 데이터베이스는 MySQL을 사용하고 있다는 것을 알 수 있고, SQL 인젝션공격이 먹힌다는 정보를 얻을 수 있다.
대표적인 SQL 인젝션 쿼리인
' or 1=1#을 입력해보자.
사용할 쿼리를 해석하면 쿼리결과는 1=1을 통해 항상 참이되고 기존코드 뒷부분을 전부 주석처리를 해버린다.
여튼 정상쿼리로 입력되어 진행된다는 것이다.
그려면 위와 같은 결과가 쫘르르륵 출력되게 된다.
단순히 ' or 1=1#뿐아니라
이제 DB의 정보를 한번 획득을 해보는 실습을 해보자
이번에 쓸것은 UNION SQL인젝션!
SQL구문중에 UNION이라는 구문이 있는데 UNION은 둘 이상의 Select문을 결합하여 하나의 결과물로 출력해주는 구문이라고 생각하면 된다.
' union select 1#이라고 입력해보자
칼럼의 갯수가 맞지 않아서 에러가 뜬다
' union select 1,2#
' union select 1,2,3#
...
이렇게 추가하면서 차례대로 입력을 해보면
' union select 1,2,3,4,5,6,7#
칼럼수가 일치해지는 구간이 생겨 결과가 출력된다.
그리고 하단을 보면
출력되는 열이 2,3,5,4열인 것을 알 수 있다.
그럼 2번열에 MySQL의 버젼을 얻어오는 시스템 변수를 아래와 같이 쳐보면
' union select 1,@@version,3,4,5,6,7#
MySQL의 버전이 출력된 것을 확인할 수 있다!!
이번에는 아래와 같이 SQL구문을 입력해보자
0' union select 1,table_name,3,4,5,6,7 from information_schema.tables#
위 구문의 해석을 미리하자면 information_schema데이터베이스 안에 속한 tables라는 테이블의 table_name 즉 DB에 등록된 모든 테이블의 목록들을 불러오는 SQL구문이다.
참고로 맨앞에 0을 넣은 이유는 앞전의 select 결과물을 무효화 시켜 쓸모없는 값들을 제외하기 위함인것!
결과는 하단에 나열하기 힘들정도로 많이 나왔다.
추가적으로 blog, users, movies라는 테이블도 보였다.
제일 크리티컬해보이는 users 테이블의 데이터들을 알아내보도록하자.
0' union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name='users'#
뒤에 where하고 조건이 더 붙었는데 users라는 테이블이름을 가진 테이블에서 column_name 즉, 칼럼들의 정보들을 가져오는 SQL구문이다.
출력결과 users라는 테이블의 열값으로는
id, login, password, email 등등 값들이 들어있는 것을 볼 수 있다.
여기까지 users라는 테이블의 존재, users안에 있는 칼럼들의 내용들을 알았으니 본격적으로 users안에 있는 정보들을 얻어보도록 하자
이번에 입력할 SQL 구문은
0' union select 1,concat(id,login),password,email,secret,6,7 from users#
concat 함수는 두개의 칼럼을 하나로 합치는 구문이다.
출력해서 볼 수 있는 칸이 4개이고 내가 보고싶은 칼럼은 5개이므로 2개를 1개로 합쳐서 출력시켜본다.
순순히 계정정보들이 나온 것을 볼 수가 있다.
차례대로 concat(id,login), password, secret, email순으로 출력되엇다.
결과적으로 SELECT SQL 인젝션은 보안을 하지 않으면 데이터베이스 정보부터해서 테이블 정보 심지어 테이블의 내용까지 전부 볼 수 있다.
보안방법
지금까지 인젝션한 SQL구문들을 보면 싱글쿼터(')에 의해서 어디까지가 SQL구문의 끝인지 알 수 있다.
그렇다면 이러한 특수문자를 필터링 하면 1차적으로 쉽게 해결될 것이다.
Bee-Box 서버의 sqli_1.php소스코드를 보자.
위 소스코드가 마찬가지로 보안하는 함수들이다. 각각 Low, Medium, High레벨
sqli_check_1, sqli_check_2함수가 들어있는 functions_external.php 소스코드를 보면
sqli_check_1함수는 addslashes함수를 통해 '를 전부 문자열로 바꿔버리고
(addslahes함수는 이전 포스팅 참고)
sqli_check_2함수는 mysql_real_escape_string함수를 통해 MySQL에서 사용되는 특수기호들을 필터링하여 삽입된 특수기호들이 SQL문법으로써 실행되지 못하도록 한다.
'Penetration Testing > Bee-Box' 카테고리의 다른 글
Bee-Box 실습글 휴재 (0) | 2018.03.04 |
---|---|
PHP - addslashes 함수 (0) | 2018.02.21 |
[Bee-Box] SSI 인젝션 (0) | 2018.02.21 |
[Bee-Box] PHP 코드 인젝션 (PHP Code Injection) (0) | 2018.02.20 |
[Bee-Box] OS 커맨드 인젝션 (0) | 2018.02.14 |