<?php
include "../config.php";
login_chk();
dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[no])) exit("No Hack ~_~");
if(preg_match('/\'/i', $_GET[pw])) exit("HeHe");
if(preg_match('/\'|substr|ascii|=/i', $_GET[no])) exit("HeHe");
$query = "select id from prob_darkknight where id='guest' and pw='{$_GET[pw]}' and no={$_GET[no]}";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_darkknight where id='admin' and pw='{$_GET[pw]}'";
$result = @mysql_fetch_array(mysql_query($query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("darkknight");
highlight_file(__FILE__);
?>
소스코드 분석
pw에서는 '만 no에서는 '과 substr,ascii등이 막혀 있다.
이것도 필터를 우회해서 blind_sql을 진행해야 한다.
풀이
우선 no=1 || length(pw) > 1 && no like 2구문을 통해 비밀번호의 길이가 1이상이고 admin의 no가 2인 것을 확인했다.
그럼 페이로드를 짤떄 id='admin'을 통해 admin의 비밀번호를 찾아내는 것 대신
no=2로 admin임을 확인할 수 있다.
no like 2 대신 ord(id)-103을 이용할 수 도 있다. ord==ascii
따라서 페이로드는
no=1 || length(pw)>1 && no like 2 구문으로 비밀번호의 길이를 알아 보고
no=1 || no like 2 && hex(mid(pw,1,1)) > 10 을 통해서 비밀번호를 유추 할 수 있다.