<?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>

 

위 소소코드를 해석하면, 우선 클라이언트의 user agent 값을 가져와 이를 query 절에 넣어 id를 조회하고, 없으면 insert 문으로 guest라는 id를 생성한다. 

테이블 chall8 의 id가 70개 이상 넘으면 chall8 테이블 내에 있는 데이터를 삭제한다. 

문제를 풀기 위해서는 클라이언트의 user agent로 admin이라는 id를 가진 값으로 insert 해야 문제가 풀리게 된다.

 

 

아래 코드를 보면 agent에는 어떠한 인자값 검사를 하지 않는다. 여기서 우리는 user agent를 변조해서 admin이라는 id를 생성할 수 있다.

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)");
}

 

fiddler로 패킷을 잡아서 http header에서 user-agent 값을 아래 값으로 변조해서 ip는 대충 아무거나 적고, id 컬럼에 admin 이라는 값으로 적고 요청을 보낸다.

 

요청을 보내고 응답 값을 보면 아래 처럼 done 이라는 문구와 14개의 id가 있다라는 것을 알 수 있다. admin 말고도 다른 쓰레기 값들이 있으니 70개까지 만들고 이 테이블의 값을 지우게 끔 요청을 계속 보낸다.

 

아래 처럼 70개의 id를 만들었다.

 

 

 user-agent 값을 필자의 경우 universe로 요청을 보내면 문제가 풀리는 것을 볼 수 있다.