728x90
<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|\./i', $_GET['id'])) exit("No Hack ~_~");
  if(strlen($_GET['id']) > 7) exit("too long string");
  $no = is_numeric($_GET['no']) ? $_GET['no'] : 1;
  $query = "select id from prob_red_dragon where id='{$_GET['id']}' and no={$no}";
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['id']) echo "<h2>Hello {$result['id']}</h2>";

  $query = "select no from prob_red_dragon where id='admin'"; // if you think challenge got wrong, look column name again.
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if($result['no'] === $_GET['no']) solve("red_dragon");
  highlight_file(__FILE__);
?>

id의 길이는 7 이하이며 no는 숫자만 가능하다. 문자가 섞이면 no는 1이 된다. 

?id='||no>%23&no=%0a자연수

%23은 url 인코딩 값이기에 php 코드 상에선 '#' 문자 하나로 해석된다. '#'는 sql에서 한 줄 주석이다. 따라서 id의 길이는 7이다. 참고로 띄어쓰기는 길이가 1로 해석되기에 모두 붙여 써야 한다.

no는 숫자만 된다고 했는데 %0a(개행문자=엔터='\n')는 써도 된다. 문자로 인식되지 않는다.

만약 자연수가 123이라면 쿼리를 웹 페이지에 출력하면 다음과 같다.

select id from prob_red_dragon where id=''||no>#' and no= 123

no= 와 123 사이에 한 칸 띄워진 형태로 보이는데 소스코드를 보면 다음과 같다.

select id from prob_red_dragon where id=''||no>#' and no=

123

개행이 적용되는 것을 알 수 있다.

빨간 글자 부분은 %23(#) 한 줄 주석에 의해 주석처리되며 %0a에 의해 no=까지만 주석처리된다. 123은 다음 줄이므로 주석처리 되지 않는다. 결국 다음과 같은 쿼리가 된다. 참고로 || 는 sql에서 or의 역할을 한다. 다만 or을 쓰면 orno형태가 되어 or 기능을 못한다. 그래서  띄어쓰기를 하려 하면 id 길이가 7이 넘게 된다. 그래서 ||를 써야 한다.

select id from prob_red_dragon where id=''||no>123

이를 기반으로 이진 탐색방식으로 no값을 추적하면 된다.

답: ?no=586482014

728x90

'Lord of SQL Injection' 카테고리의 다른 글

frankenstein  (2) 2023.01.02
blue_dragon  (0) 2023.01.02
green_dragon  (2) 2023.01.02
evil_wizard  (0) 2023.01.02
hell_fire  (2) 2023.01.01

+ Recent posts