링크로 들어가면 35번 문제를 확인할 수 있다.
소스코드를 보러 가야겠다 ^_^
소스코드
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 35</title>
<head>
<body>
<form method=get action=index.php>
phone : <input name=phone size=11 style=width:200px>
<input name=id type=hidden value=guest>
<input type=submit value='add'>
</form>
<?php
$db = dbconnect();
if($_GET['phone'] && $_GET['id']){
if(preg_match("/\*|\/|=|select|-|#|;/i",$_GET['phone'])) exit("no hack");
if(strlen($_GET['id']) > 5) exit("no hack");
if(preg_match("/admin/i",$_GET['id'])) exit("you are not admin");
mysqli_query($db,"insert into chall35(id,ip,phone) values('{$_GET['id']}','{$_SERVER['REMOTE_ADDR']}',{$_GET['phone']})") or die("query error");
echo "Done<br>";
}
$isAdmin = mysqli_fetch_array(mysqli_query($db,"select ip from chall35 where id='admin' and ip='{$_SERVER['REMOTE_ADDR']}'"));
if($isAdmin['ip'] == $_SERVER['REMOTE_ADDR']){
solve(35);
mysqli_query($db,"delete from chall35");
}
$phone_list = mysqli_query($db,"select * from chall35 where ip='{$_SERVER['REMOTE_ADDR']}'");
echo "<!--\n";
while($r = mysqli_fetch_array($phone_list)){
echo htmlentities($r['id'])." - ".$r['phone']."\n";
}
echo "-->\n";
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>
입력폼을 주의깊게 보자!
id값은 guest로 고정되어 있고 변수명 phone으로 입력값이 전달된다.
쿼리문이 자주 등장하는 걸로 보아 SQL 인젝션 문제인 것 같으므로 쿼리가 등장하는 부분을 따로 보자!
if($_GET['phone'] && $_GET['id']){
if(preg_match("/\*|\/|=|select|-|#|;/i",$_GET['phone'])) exit("no hack");
if(strlen($_GET['id']) > 5) exit("no hack");
if(preg_match("/admin/i",$_GET['id'])) exit("you are not admin");
mysqli_query($db,"insert into chall35(id,ip,phone) values('{$_GET['id']}','{$_SERVER['REMOTE_ADDR']}',{$_GET['phone']})") or die("query error");
echo "Done<br>";
}
if문은 건너뛰고 mysqli_query 라인을 보면
insert into chall35(id,ip,phone) values('{$_GET['id']}','{$_SERVER['REMOTE_ADDR']}' {$_GET['phone']
chall35 테이블에
① id값으로 $_GET['id']을 넣고
② ip값에 $_SERVER['REMOTE_ADDR'](내 서버의ip값)을 넣고
③ phone값으로 $_GET['phone']을 넣는다.
만약 phone값으로 01011111111을 입력하면 아래와 같은 형식으로 DB에 데이터가 쌓인다.
id
|
ip
|
phone
|
guest
|
내 서버 ip값(xxxxxxxxxxx)
|
01011111111
|
$isAdmin = mysqli_fetch_array(mysqli_query($db,"select ip from chall35 where id='admin' and ip='{$_SERVER['REMOTE_ADDR']}'"));
if($isAdmin['ip'] == $_SERVER['REMOTE_ADDR']){
solve(35);
mysqli_query($db,"delete from chall35");
}
첫 번째 라인을 해석하면
select ip from chall35 where id='admin' and ip='{$_SERVER['REMOTE_ADDR']}'
chall35 테이블에서
조건 ① id = admin
② ip='{$_SERVER['REMOTE_ADDR'](ip값이 내 서버의 ip값과 같다)
두 조건을 동시에 만족하는 ip를 선택하여 isAdmin값에 담고 선택한 ip값과 내 서버 ip값이 같은 경우 문제가 풀린다.
그런데 phone값으로 3을 입력하면 DB에 아래와 같은 데이터가 쌓이고
id
|
ip
|
phone
|
guest
|
내 서버 ip값(xxxxxxxxxxx)
|
01011111111
|
쿼리문 조건 중 첫 번째인 id=admin 을 만족하지 못하기 때문에 어떤 것도 select 되지 않고
$isAdmin 에 아무런 값도 존재하지 않게 된다.
따라서 solve 조건을 만족하지 못하면서 문제가 풀리지 않는다.
해결
문제를 풀기 위해선 ip값이 내 서버의 ip값과 같으면서 id=admin이어야 한다.
ip값이 내 서버 ip값과 같은 경우 문제가 풀리기 때문에 쿼리문에서 조건에 맞는 ip가 선택될 수 있도록 해야한다. 우리는 phone값을 입력하여 조작할 수 있으므로 여기서 sql 인젝션을 통해 id값에 admin이 담길 수 있게 변환해야 한다.
따라서 입력폼에 a),('admin','ip값~',01012345678) 을 입력해주면
id
|
ip
|
phone
|
guest
|
내 서버 ip값(xxxxxxxxxxx)
|
a
|
admin
|
내 서버 ip값(xxxxxxxxxxx)
|
01012345678
|
id값이 admin이면서 ip가 내 서버의 ip인 값이라는 조건을 모두 만족하면서 문제가 풀린다.
(빨간 글씨는 phone값으로 입력하여 추가된 부분)
35 point 획득 :D
'Webhacking' 카테고리의 다른 글
[Webhacking.kr] old-27번 풀이 (0) | 2022.12.22 |
---|---|
[Webhacking.kr] old-14번 풀이 (0) | 2022.12.22 |
[Webhacking.kr] old-12번 풀이 (0) | 2022.12.21 |
[Webhacking.kr] old-19번 풀이 (0) | 2022.12.21 |
[Webhacking.kr] old-24번 풀이 (0) | 2022.12.21 |