[webhacking.kr 27번]
[필히 본인이 풀어보시고 정말 안되겠다면 다음의 풀이를 확인하시길 바랍니다.]
[그림 1] 27번 문제 페이지
27번문제는 SQL Injection에 관한 문제이다.
이문제는 앞서 풀었던 18번 문제와 비슷하지만 좀더 문자 필터링이 추가된 문제이다.
<html> <head> <title>Challenge 27</title> </head> <body> <h1>SQL INJECTION</h1> <form method=get action=index.php> <input type=text name=no><input type=submit> </form> <? if($_GET[no]) { if(eregi("#|union|from|challenge|select|\(|\t|/|limit|=|0x",$_GET[no])) exit("no hack"); $q=@mysql_fetch_array(mysql_query("select id from challenge27_table where id='guest' and no=($_GET[no])")) or die("query error"); if($q[id]=="guest") echo("guest"); if($q[id]=="admin") @solve(); } ?> <!-- index.phps --> </body> </html> |
[표 1] 소스코드(index.phps)
사실 본인이 문제를 풀 당시에는 소스코드가 오픈되어 있는 줄 몰랐다. 소스코드를 알지 못한 상태에서 여러가지의 쿼리를 삽입해보며 필터링되는 문자들을 일일이 찾았다. 하지만 이런 방법을 먼저 선행하는 것이 더욱 SQL injection을 공부하는데 좋다고 생각을 한다.
실제로 회사에 가서 모의점검을 한다고 하면 이런 소스코드는 공개되지 않는 것은 당연한 애기이고, 머리속에서 소스코드를 예상하며 어떻게 쿼리를 생성해 놨구나!라는 생각을 하면 후에 창의적 사고(?) 및 응용력이 더 좋아지라 본다.
다시 문제풀이와 연관되어 생각해보자.
처음 본인이 삽입한 쿼리문은 1이다.
[그림 2] '1'입력
no라는 변수에 1이 삽입이 되며 DB에 1번째 데이터 id는 guest구나라고 생각해볼 수 있다.
그렇다면 admin계정은 2번째나 0번째에 있지 않을까?라고 생각해볼 수 있다. 한번 삽입해보자!@
[그림 3] '2','3'..입력
하지만 쿼리 에러문을 출력해준다.
내 예상 대로라면 쿼리문은 아래와 같았다.
select id from challenge27_table where no=($_GET[no])
물론 위의 쿼리라 하면 2를 삽입했을 때 다른 계정이 출력되는 것이다.
하지만 앞에서 또 다른 조건이 존재하기 때문에!! "두개이상의 조건이 이어진다"라는 생각을 여기서 해야한다.
[그림 4] '3 or 1' 입력
[그림 4]와 같은 결과를 볼 때 두개의 조건을 만족한다는 것을 생각해 볼 수 있다.
(no=3 or no=1 : no값이 3이니 앞의 조건은 거짓이 되어 버리고 or 이후의 조건으로 만족시키니)
이런 식으로 삽입한 쿼리가 정상적인지! 에러를 내는지!를 판단한것이 ErrorBased Sql injection이다.
이제 소스코드를 우리는 알고 있으니 이를 기반으로 작성한 쿼리문을 살펴보자.
-1) or no Like 2 --
여기서 중요한 부분은 ')'가 왜 있는지 Like는 무엇이며 --는 어떻게 사용되는지이다.
1. ')'
no=($_GET[no])
코드에 존재하는 쿼리에서는 no변수의 값을 괄호로 둘러 싸고 있으니 ')'를 넣어 닫아주는 역할을 해주어야 한다.
그리고 그 이후의 같은 어차피 주석처리하면 되니깐~ㅋ
2. 'Like'
'='이 필터링 되어 있어서 Like와 같은 sql 문법을을 사용하였다.
3. ' -- '
'--'는 1번에서 언급했듯이 삽입한 문자열 뒤에오는 것을 주석처리하면서 내가 쿼리문을 완성시키는 것이다.
여기서 더욱 중요한 부분은 '--'앞뒤에 공백이 있어야 한다는 것이다.
sql 쿼리문은 공백을 중심으로 앞 문자와 뒤문자를 구분하기 때문에 DB를 다루다보면 저 사소한 공백하나로 에러를 발생하고 왜 안되지!! 이러고 있다...ㅠ