sql injection 문제이다. 소스 보기를 하면 몇몇개의 문자들이 필터링 되어 있다.

<?php
if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/ |\/|\(|\)|\||&|select|from|0x/i",$_GET['no'])) exit("no hack");
  $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']=="guest") echo "hi guest";
  if($result['id']=="admin"){
    solve(18);
    echo "hi admin!";
  }
}

 

no 값에 1을 주면 "hi guest" 라는 문구가 출력이 된다. 

위 코드에 주석으로 no=2 가 admin 이라고 했으니 테이블 구조는 다음과 같을 것이다.

 

no id
1 guest
2 admin

 

위 sql query를 보면 no에 injection을 할 수 있는데, 우리의 목표는 admin 으로 query의 결과를 만드는 것이다. 

 

만약 ?no=1 or no=2 라고 요청을 보내면 id="guest" and no=1 이라는 값이 이미 참 이기 때문에 뒤에 no=2라고 해도 guest 라는 결과값을 얻을 수 밖에 없다. 

 

그렇다면 ?no=0 or no=2 라는 요청을 보내면 id="guest" and no=0 이라는 값은 거짓이고 or 연산으로 no=2라는 값을 찾으면 성공적으로 admin이라는 결과를 얻을 수 있다. 하지만 문제에서 공백을 필터링하고 있으므로 공백을 우회하기 위해 %0a 문자열을 사용한다.

 

?no=0%0aor%0ano=2