이번에는 webhacking.kr의 old-07 문제를 풀어보려고 한다.
문제에 들어가면 다음과 같이 Admin page라는 말과 함께 auth 버튼, 그리고 가장 중요한 소스 코드를 볼 수 있는 view-source 하이퍼링크가 있다.
view-source를 눌러 코드를 둘러보자.
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 7</title>
</head>
<body>
<?php
$go=$_GET['val'];
if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");
$db = dbconnect();
$rand=rand(1,5);
if($rand==1){
$result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
}
if($rand==2){
$result=mysqli_query($db,"select lv from chall7 where lv=(($go))") or die("nice try!");
}
if($rand==3){
$result=mysqli_query($db,"select lv from chall7 where lv=((($go)))") or die("nice try!");
}
if($rand==4){
$result=mysqli_query($db,"select lv from chall7 where lv=(((($go))))") or die("nice try!");
}
if($rand==5){
$result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
}
$data=mysqli_fetch_array($result);
if(!$data[0]) { echo("query error"); exit(); }
if($data[0]==1){
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
}
elseif($data[0]==2){
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
solve(7);
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>
코드를 보니 val 파라미터에 들어간 데이터를 간단한 검증을 거친 후 바로 쿼리에 삽입하여 동작하는 시스템으로 보인다.
하지만, 자세히 보니 바로 삽입을 할 수는 없고 1에서 5까지 랜덤한 값을 하나 정하고 그 값에 따라 괄호로 padding하는 부분이 있었고, 여기서 낚이지 말아야겠다는 생각을 하게 되었다.
그리고 밑에 data[0]이라는 부분이 많이 보이는데, 이 부분은 PHP
에서 mysql
SELECT
를 하고 mysqli_fetch_array
함수를 통해 데이터를 받아오게 되면 array 형식으로 리턴되기 때문에 나오는 가장 첫번째 값을 받아오기 위해서 0번째 값을 호출하는 것이다.
이제 코드도 받았겠다 본격적으로 문제 풀이에 임해보자.
사실 처음에는 SQL Injection
의 정석이라고도 불릴 수 있을만큼 흔한 다른 row의 참조 (OR lv like 2
등등)를 사용하는 문제인 줄 알고 삽집을 좀 했다 ㅎㅎ....;;
그렇게 삽질을 좀 하다가 눈에 들어온 것이 있는데, 바로 이 부분의 코드이다.
select lv from chall7
불러오는 row의 갯수가 하나였다.
그럼 UNION을 통해서 데이터의 갯수를 일방적으로 변경한다면?
기본 쿼리는 변경할 수 없었고, lv 값은 정확히 2가 되어야 하고, 2는 ASCii 표준에서 50이므로 생각했던 구문은 다음과 같았다.
SELECT lv FROM chall7 WHERE lv=(0)UNION(SELECT(CHAR(50))
따라서 위의 가설을 검증하기 위해 val 파라미터에 다음의 값을 넣었다.
?val=0)UNION(SELECT(CHAR(50))
예상이 맞았다.
앞서 예상했던 바와 같이 한번에 되진 않았고, 여러번 돌려야 하긴 했지만 결국 풀이에 성공했다.
'보안공부 > Webhacking.kr 풀이' 카테고리의 다른 글
Webhacking.kr 36번 문제 풀이 (0) | 2019.09.17 |
---|---|
Webhacking.kr 8번 문제 풀이 (0) | 2019.09.17 |
Webhacking.kr 60번 문제 풀이 (0) | 2019.09.15 |
Webhacking.kr 48번 문제 풀이 (0) | 2019.09.14 |
webhacking.kr 44번 문제 풀이 (0) | 2019.09.13 |