WarGame & Conference/_Webhacking.kr
webhacking.kr 39번 문제
Dakuo
2010. 3. 23. 16:16
webhacking.kr 39번 문제를 클릭하면 다음과 같은 페이지가 뜬다.
아무글자나 입력해서 쿼리를 전송해보니까
Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /www/webhacking_kr/challenge/bonus/bonus-10/index.php on line 18
위와 같은 경고가 뜬다. mysql_fetch_array()를 호출할때 사용한 쿼리가 틀려서
18번째 라인에서 에러가 났다는 뜻이다.
소스보기로 왜 에러가 발생했는지 살펴보자.
오류에 대한 원인은 없고 다만,
<!-- index.phps --> 라고 주석이 달려있다. 해당 주소로 이동해보자.
(http://webhacking.kr/challenge/bonus/bonus-10/index.phps)
다음과 같은 소스가 보여진다.
<html>
<head>
<title>Chellenge 39</title>
</head>
<body>
<?
$pw="????";
if($_POST[id])
{
$_POST[id]=str_replace("\\","",$_POST[id]);
$_POST[id]=str_replace("'","''",$_POST[id]);
$_POST[id]=substr($_POST[id],0,15);
$q=mysql_fetch_array(mysql_query("select 'good' from zmail_member where id='$_POST[id]"));
if($q[0]=="good") die("Password is $pw");
}
?>
<form method=post action=index.php>
<input type=text name=id maxlength=15 size=30>
<input type=submit>
</form>
</body>
</html>
소스를 분석해보자.
Warning: mysql_fetch_array(): 에러가 뜨는 mysql_fetch_array() 호출문인
$q=mysql_fetch_array(mysql_query("select 'good' from zmail_member where id='$_POST[id]"));
자세히 살펴보면 id = '$_POST[id] 에서 싱글쿼터가 닫혀 있지 않다.
따라서 에러가 발생하는 것이다.!!!
이제 에러 부분을 찾았고 $_POST[id] 에 대한걸 더 분석해보면
<input type=text name=id maxlength=15 size=30> // 15글자를 입력받는 id 라는 텍스트 폼을 만든다
이 폼에 입력을 하게되며
$_POST[id]=str_replace("\\","",$_POST[id]);
$_POST[id]=str_replace("'","''",$_POST[id]);
$_POST[id]=substr($_POST[id],0,15);
위의 세가지 과정을 거쳐 쿼리로 전송된다.
str_repleace 는 문자열에서 지정한 문자를 다른문자로 바꾸겠다는 뜻이다.
즉, 첫문장 $_POST[id]=str_replace("\\","",$_POST[id]); 에서
우리가 입력한 역슬래시(\) 가 없어지게 된다.
$_POST[id]=str_replace("'","''",$_POST[id]); 에서는
싱글쿼터( ' )가 더블쿼터( '' )로 바뀌게 된다.
substr() 함수는 입력한 지정된 문자열에서 지정한 부분만을 가져오는 함수이다.
따라서, $_POST[id]=substr($_POST[id],0,15);
위 두문장을 통해 변형된 $_POST[id] 값중에서 0번 인덱스부터 15개의 문자를 가져온다.
이제 어떻게 쿼리를 보내야 할지 생각을 해보자.
일단 아무값이나 입력한다 쳐도 마지막에 싱글쿼터로 꼭 닫아줘야 한다.
즉, admin' 이런식으로 쿼리가 전송되야 에러가 발생하지 않을것이다.
그런데 싱글쿼터(')를 입력해도 str_repleace 를 통하여 더블쿼터('')로 바뀌게 된다.
따라서 특문처리인 \' 이렇게 입력을 하려고 해도 \ 는 없어지기에 이방법도 실패한다.
해답은 substr에 의해 15글자만 가져온다는 것에 있다.
즉 홀수의 글자를 가져오기에 '' 에서 하나가 잘라져 나가 ' 로 보낼수 있는것이다.
14글자를 채운뒤 ' 쿼터를 입력하면 '' 쿼터로 변한다 16글자.
이중 0번 인덱스부터 15 문자를 가져오기에
마지막 쿼터 하나가 잘라져 나가 --------------' 이런식으로 완성이 될것이다.
따라서 admin ' 이렇게 쿼리를 전송한다면 admin '' 으로 변한뒤
0번 인덱스부터 15글자를 가져와서 최종 쿼리는 admin' 이 될것이다.
문제가 풀려서 Password 값이 나오는 것을 확인할수 있다.