웹/webhacking.kr

webhacking.kr 27번

최경환의 해킹공부 2021. 2. 17. 09:17

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 27</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
<input type=text name=no><input type=submit>
</form>
<?php
  if($_GET['no']){
  $db = dbconnect();
  if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
  $r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
  if($r['id']=="guest") echo("guest");
  if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>

문제에서부터 sql injection 문제라는 것을 알려주고 있기 때문에 바로 소스코드로 넘어가겠습니다.  일단 preg_match 함수를 통해 select, #, 공백, ( 등의 문자들이 필터링됩니다. 그리고 no의 값을 get 형식으로 받아 id를 select하는 쿼리문에서 admin이라는 id 정보를 가져오게 되면 문제가 풀립니다. 소스코드 자체를 해석하는 것에는 큰 문제가 없습니다.

 

먼저 no에 단순히 1을 넣어주게되면 guest를 가져오는 것 같습니다.

그리고 열심히 쿼리문을 조작해봤습니다.(삽질을 조금 하면 풀리는 문제였습니다.)

 

일단 문제코드를 자세히 보면 주석으로 admin의 넘버는 2라는 것을 그냥 가르쳐 주고 있습니다. 그렇기 때문에 no를 잘 조작하면 admin을 가져올 수 있을 것 같습니다.

 

일단 이런식으로 쿼리문을 짜봤습니다. 조금 더 가독성 있게 적으면

 

no=1) or id like "admin" and no like 2 -- 라는 쿼리문입니다. 이런식으로 넣게 되면 아래와 비슷한 결과를 가져올 수 있습니다.

이렇게 쿼리문이 기존에 문제에서 주어진 쿼리문이라고 생각하면 됩니다. 여기서 아래처럼 조건을 추가하게 되면

하나의 id값을 더 가져올 수 있습니다. 이를 이용해서 쿼리문을 작성하려고 했으나 어딘가 잘 안 되어서 조금더 삽질을 했습니다.

위의 쿼리문이 최종 쿼리문입니다. 아마 공백을 개행문자(%0a)가 아니라 탭(%09)를 사용해야 하는 것 같습니다. 이렇게 넣어주게 되면 문제가 풀리게 됩니다. 쿼리문의 이해가 있다면 점수가 말해주듯 난이도는 좀 낮은 문제였던 것 같습니다.