본문 바로가기

웹/webhacking.kr

webhacking.kr 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>

이 문제는 바로 소스코드 분석을 한 뒤 SQL injection을 이용해 푸는 문제입니다.

 

처음 소스코드를 봤을 때 처음보는 유형이었던 것이 지금까지 풀었던 SQL injection 문제는 get방식으로 받는 값을 이용하여 쿼리문을 조작해서 비밀번호를 알아내거나 id를 admin으로 수정하면 풀리는 문제들을 풀었는데 이 문제에서는 갑자기 $_SEVER['REMOTE_ADDR'], getenv['HTTP_USER_AGENT']등의 값이 보이고 db에서 데이터를 가져오는 쿼리문에서 조건문에 해당하는 값들이 $_SEVER['HTTP_USER_AGENT']의 값 등이어서 당황했습니다.

 

그래서 찾아보니 burp suite를 이용해서 현재 패킷의 정보들 중 user_agent의 값을 수정해서 제가 원하느 쿼리문을 완성시키는 방식의 공격을 해야했습니다. 그러면 이제 코드를 분석해 보겠습니다.

 

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

 

이 부분을 보면, 단순하게 db에 연결해서 데이터를 가져옵니다. 이때 agent의 값이 패킷의 user_agent값을 가져왔을 때의 id를 가져오고 배열화 시킨 값의 id값이 admin일 때 문제가 풀리는 구조입니다.

 

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

 

이 문제의 핵심 부분입니다. 만약에 db에서 가져온 값이 없을 경웨 insert문을 통해 db에 원하는 정보를 저장할 수 있는 쿼리문이 존재합니다. 그래서 이 쿼리문을 이용해 id='admin' 정보를 db에 저장하고, 다시 새로고침한 후 저장할때 agent 값으로 패킷의 user_agent의 값을 수정해주어서 id='admin'이라는 정보를 가져오면 될 것 같습니다.

먼저 패킷을 위조했을 때 제대로 쿼리문이 작동하는 지 보기 위해 단순히 싱글 쿼터로 패킷을 조작해서 보내주었더니 예상대로 query error 메세지가 뜨는 것을 확인했고 그렇기 때문에 수정한 부분을 이용해서 공격을 시도하면 될 것 같습니다.

 

지금 done이 뜬 상황입니다. 이 이유는 제대로 값이 db에 저장되었다는 뜻인 것 같습니다. 만약 저 값처럼 db에 넣게 된다면 쿼리문은

insert into chall8(agent,ip,id) values('aaaa',1.1.1.1','admin'), ('bbbb','{$ip}','guest')" 라는 쿼리문이 완성되고 그렇게 되면 agent, ip, id의 값에 제가 원하는 값이 저장되게 됩니다.

그 후 제가 저장한 agent의 값이 aaaa이기 때문에 새로 고침 후 burp suite를 이용해 user-agent의 값을 aaaa로 수정해서 보내게 되면 select 쿼리문의 whre agent='aaaa'가 되기 때문에 제가 저장해 놓은 id값이 admin을 가져오게 되고, 문제 조건을 만족하여 문제가 풀리게 됩니다.

' > webhacking.kr' 카테고리의 다른 글

webhacking.kr 12번  (0) 2021.02.01
webhacking.kr 11번  (0) 2021.02.01
webhacking.kr 6번  (0) 2021.01.31
webhacking.kr 5번  (0) 2021.01.31
webhacking.kr 10번  (0) 2021.01.27