어려웠던 문제.
소스코드
<?php
error_reporting(0); // Turn off all error reporting
include("./config.php"); // hidden column name
include("../lib.php"); // auth_code function
mysql_connect("localhost","adm1nkyj","adm1nkyj_pz");
mysql_select_db("adm1nkyj"); // DB NAME
/**********************************************************************************************************************/
function rand_string()
{
$string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz";
return str_shuffle($string);
}
function reset_flag($count_column, $flag_column)
{
$flag = rand_string();
$query = mysql_fetch_array(mysql_query("SELECT $count_column, $flag_column FROM findflag_2"));
if($query[$count_column] == 150)
{
if(mysql_query("UPDATE findflag_2 SET $flag_column='{$flag}';"))
{
mysql_query("UPDATE findflag_2 SET $count_column=0;");
echo "reset flag<hr>";
}
return $flag;
}
else
{
mysql_query("UPDATE findflag_2 SET $count_column=($query[$count_column] + 1);");
}
return $query[$flag_column];
}
function get_pw($pw_column){
$query = mysql_fetch_array(mysql_query("select $pw_column from findflag_2 limit 1"));
return $query[$pw_column];
}
/**********************************************************************************************************************/
$tmp_flag = "";
$tmp_pw = "";
$id = $_GET['id'];
$pw = $_GET['pw'];
$flags = $_GET['flag'];
if(isset($id))
{
if(preg_match("/information|schema|user/i", $id) || substr_count($id,"(") > 1) exit("no hack");
if(preg_match("/information|schema|user/i", $pw) || substr_count($pw,"(") > 1) exit("no hack");
$tmp_flag = reset_flag($count_column, $flag_column);
$tmp_pw = get_pw($pw_column);
$query = mysql_fetch_array(mysql_query("SELECT * FROM findflag_2 WHERE $id_column='{$id}' and $pw_column='{$pw}';"));
if($query[$id_column])
{
if(isset($pw) && isset($flags) && $pw === $tmp_pw && $flags === $tmp_flag)
{
echo "good job!!<br />FLAG : <b>".auth_code("adm1nkyj")."</b><hr>";
}
else
{
echo "Hello ".$query[$id_column]."<hr>";
}
}
} else {
highlight_file(__FILE__);
}
?>
id pw flag 세 개의 변수를 입력받는다.
id
와 pw
에는 information schema user이 걸려있다. information_schema는 못 쓸듯 하다. 그리고 ( )
를 한 번 까지 사용할 수 있다.
flag
는 비교적 자유롭게 사용할 수 있으나, 중요 쿼리에 사용되지 않는다..
코드를 보면, pw와 flag를 150번의 시도 내에 획득하면 된다는 것 같다. 언뜻 봐서는 blind sql injection으로 보인다.
그러나, 변수명이 하나도 주어지지 않았다. 사실 그것이 이 문제의 핵심이다.
아이디 알아내기
pw=999' or 1=1 -- g
만 해도 아이디를 구할 수 있다. 쉬우니까 패스
id = adm1ngnngn