<?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
'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 |