카테고리 없음

[Web] SECGAME 'Onion' write-up

luckyd8 2025. 7. 10. 23:58

 
SECGAME 'Onion' 문제를 풀어보았다. 
 
http://158.247.215.127:10012/

Onion

158.247.215.127:10012

 
 
처음 문제에 접속하면 다음과 같은 화면이 뜬다. 먼저 로그인(Login) 기능에서 SQL Injection 공격을 시도했다.

 
흔히 사용되는 SQL문을 유추해 다음과 같은 공격문을 입력했다.

' OR 1=1 #

 
하지만 아이디와 패스워드를 모두 입력하라는 경고 문구가 출력되었다. 따라서 우선 정상적으로 회원가입을 진행한 뒤, 게시판 기능에서 새로운 SQLi 공격을 시도해 보기로 했다.

 
회원가입(Register) 기능이 있기 때문에, 회원가입 후 게시판(Board)에 접근했다.

게시판은 글 검색 기능이 존재했고, 이 기능 내부에서 실행되는 SQL 쿼리를 유추해 UNION SQL 방식을 시도하고자 했다. 
UNION SQL Injection을 사용하려면 앞선 원래 쿼리와 UNION 뒤 SELECT 구문이 컬럼 개수와 데이터 타입이 일치해야 한다는 조건이 필요하다. 이를 확인하기 위해, 먼저 컬럼 개수를 알아내고자 했다. 
 

컬럼 개수 찾기

숫자 1만 입력했을 때는, 아무 데이터도 출력되지 않았다. 이는 컬럼 개수가 1보다 크다는 것으로, 숫자 개수를 하나씩 늘려가며 공격을 반복했다. 
숫자와 컬럼 개수가 일치하지 않을 경우,  SQL 오류가 발생하거나 아무 데이터도 출력되지 않는다. 에러 없이 정상적으로 출력될 때까지 숫자를 하나씩 추가하며 입력해봄으로써 컬럼 개수를 추측할 수 있다.

' UNION SELECT ALL 1 #

 

1, 2, 3까지 입력했을 때, 에러 없이 화면에 출력되었으므로, 쿼리 개수가 3개임을 알 수 있었다. 또한, 1, 2, 3이 각각 순서대로 출력된 것을 통해 컬럼 위치도 쿼리에서 지정한 순서와 동일하다는 것도 확인할 수 있었다.

 
 

DB 이름 찾기

이후 FLAG를 찾기 위해 데이터를 효과적으로 추출하려면, 우선 데이터베이스(DB) 이름을 아는 것이 중요하다. 
DB 이름을 찾기 위해 다음과 같은 명령어를 입력했다. 
- database(): MySQL 내장함수로, 현재 연결된 데이터베이스의 이름을 문자열로 반환함

' UNION SELECT ALL 1, 2, database() #

 
다음과 같은 문자열의 출력을 통해, 서버에서 사용 중인 DB의 이름이 'sitedb'임을 알 수 있었다. 

 
 

TABLE 이름 찾기

DB 속 table 이름을 찾기 위해 다음과 같은 명령어를 입력한다.
- table_name: DB 내 테이블 이름이 저장된 컬럼 (information_schema.columns 테이블 내에 존재)
- information_schema: MySQL 서버 내에 존재하는 DB의 메타 정보를 저장한 데이터베이스 (메타 정보: 테이블, 칼럼, 인덱스 등의 스키마 정보)
 ** informantion_schema에 대해 밑에서 자세히 설명함
 + information_schema.tables:  DB(information_schema) 속 tables 테이블로부터 table_name 컬럼을 조회함
- table_schema: 해당 테이블이 속한 데이터베이스의 이름이 저장된 컬럼 (information_schema.columns 테이블 내에 존재)

'UNION SELECT 1, 2, table_name from information_schema.tables where table_schema = 'sitedb' #

 
다음과 같은 문자열의 출력을 통해, sitedb 데이터베이스에는  board, hahaha..., users 라는 총 세 개의 테이블이 존재함을 확인할 수 있었다. 

 
 

COLUMN 이름 찾기

board 테이블은 게시판과 관련된 데이터를, users 테이블은 사이트의 회원 정보와 관련된 데이터를 담고 있을 가능성이 높다. 따라서 hahaha... 테이블을 먼저 확인해보기로 했다. 알 수 없는 무작위의 문자열이 FLAG 값과 유사해 보였다..
다음과 같이 명령어를 입력한다. 
- column_name: 특정 테이블 속 컬럼의 이름을 저장한 컬럼 (information_schema.columns 테이블 내에 존재)

' UNION SELECT ALL 1,2,column_name from information_schema.columns where table_name='hahahahahathisissecrettable5ebe2294ecd0e0f08eab7690d2a6ee69'#

 
출력된 문자열을 통해, hahaha... 테이블 속에는 idx, super_secret_falg_327abc... 라는 총 두 개의 컬럼이 존재함을 확인할 수 있었다.

 
 

데이터 추출

이제 컬럼 속 실제 데이터를 조회하는 단계이다. flag 정보가 포함되어 있을 것으로 추측되는 super_secret_falg_327abc... 컬럼을 조회했다. 
다음과 같이 명령어를 입력한다.

' UNION SELECT 1, 2, super_secret_flag_327a6c4304ad5938eaf0efb6cc3e53dc FROM sitedb.hahahahahathisissecrettable5ebe2294ecd0e0f08eab7690d2a6ee69 #

 
다음과 같이 FLAG 값을 획득할 수 있다. 

 

더보기

informantion_schema

: MySQL 서버 내에 존재하는 DB의 메타 정보를 저장한 데이터베이스 (메타 정보: 테이블, 칼럼, 인덱스 등의 스키마 정보)

- 각 데이터베이스에 대한 정보들을 저장해 놓은 데이터베이스

- DBMS에 의해 자동 생성되는 메타데이터 데이터베이스 (사용자 수정 불가, 읽기 전용)

- 현재 서버에 존재하는 DB, 테이블, 컬럼 정보를 조회하기 위한 시스템 데이터

 

문제에서 사용된 테이블

information_schema.tables: 모든 데이터베이스의 테이블 정보를 저장한 테이블

information_schema.columns: 모든 데이터베이스의 컬럼 정보를 저장한 테이블

 

문제에서 사용된 컬럼

table_schema: 해당 테이블 또는 컬럼이 속한 데이터베이스의 이름을 나타내는 컬럼

table_name: 데이터베이스 내 테이블 이름이 저장된 컬럼

colunm_name: 특정 테이블의 컬럼 이름이 저장된 컬럼

 

information_schema
tablescolumns
table_schema, table_nametable_schema, table_name, column_name