소스코드를 보면
if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack"); // 필터링을 보면 db 추출은 불가능할거 같다
// admin 이 2번에 있다는 것을 알려주고 공격 포인트!
$result = mysqli_fetch_array(mysqli_query($db,"select id from chall18 where id='guest' and no=$_GET[no]")); // admin's no = 2
if($result['id']=="admin"){ // id 가 admin 이면 문제가 풀린다
solve(18);
echo "hi admin!";
}
늘 하던데로... 공격구문을 짜보자
select id from chall18 where id='guest' and no=$_GET[no]
여기서 일단 1을 넣으면 guest가 되기 때문에 거짓으로 만들기 위해 1이 아닌 값을 넣는다
나는 0을 넣겠다
그리고 둘 중하나면 참 이라는 뜻을 가진 or 을 넣고
우리는 id가 admin을 원하기 때문에 id = 'admin'을 넣어주고
no 도 2를 맞춰 줘야하기 때문에 and no = 2 를 넣어준다
한번 정리 해보면
select id from chall18 where id='guest' and no= 0 or id='admin' and no=2 가 된다
이렇게 되면 id가 guest이고 no가 0 이거나 id가 admin이고 no가 2인 값을 찾기 때문에
앞에 id가 guest이고 no가 0은 존재하지 않아 거짓이므로 해당이 안돼고
id가 admin이고 no가 2는 존재하기 때문에 참이되서 id는 admin이 된다
왜 no가 2냐 말하면... 소스코드에 있다
하지만 0 or id='admin' and no=2 이렇게 제출하면 필터링에 걸리기 때문에
필터링을 우회하는 값들로 바꿔서 만들면
0%09or%09id='admin'%09and%09no=2
이제 제출하면 문제가 풀린다