SQL Injection 심화 — DB 정찰에서 OS 명령 실행까지

🛡️ 강사 제공 인가된 실습 환경에서 수행

이번에도 SQL Injection 문제이다.

지난번에 풀었던 4-1, 4-2 문제보다 난이도가 조금 더 올라간 문제였던 것 같다.

사실 SQL Injection 자체의 원리는 이제 어느 정도 익숙해졌다.

SQL Injection에서 가장 많은 시간이 필요한 부분은 결국 현재 서비스가 어떤 SQL 쿼리를 구성하고 있는지 추론하는 과정이라고 생각한다.

입력값이 쿼리의 어느 부분에 삽입되는지, 컬럼 개수는 몇 개인지, 어떤 DBMS를 사용하는지 등을 하나씩 확인하면서 공격 방향을 잡는 것이 핵심이다.


정찰

게시판 구조는 특별한 기능 없이 상단에 검색창이 있고 아래에 게시글 목록이 출력되는 형태였다.

검색 기능은 GET 방식으로 전달되는 q 파라미터를 통해 동작하고 있었다.

먼저 SQL Injection 가능 여부를 확인하기 위해 작은따옴표(')를 입력해보았다.

'

그 결과 SQL 구문 오류가 발생하면서 SQL Injection 취약점이 존재하는 것을 확인하였다.


컬럼 수 파악

SQL Injection이 가능한 것을 확인했으므로 다음 단계로 현재 SELECT 쿼리의 컬럼 개수를 확인하였다.

일반적으로 ORDER BY 구문을 이용하여 컬럼 개수를 확인할 수 있다.

' ORDER BY 1--
' ORDER BY 2--
' ORDER BY 3--

숫자를 증가시키면서 요청을 보내고 에러가 발생하는 지점을 확인한다.

이번 문제에서는:

  • ORDER BY 5 → 정상 출력
  • ORDER BY 6 → 에러 발생

하는 것을 확인하였다.

따라서 해당 쿼리는 5개의 컬럼을 반환하고 있다고 판단하였다.

컬럼 개수 = 5


출력 위치 확인

UNION 기반 SQL Injection을 진행하기 위해 어떤 컬럼이 화면에 출력되는지 확인하였다.

테스트:

' UNION SELECT 1,2,3,4,5--

결과 본문 영역에 특정 값이 출력되는 것을 확인했고, 4번째 컬럼이 화면에 출력되는 위치라는 것을 확인하였다.

따라서 이후 원하는 데이터를 추출할 때 4번째 컬럼 위치에 값을 출력하도록 진행하였다.


DBMS 종류 확인

처음에는 MySQL 문법을 기준으로 접근하였다.

하지만 예상했던 함수와 문법이 정상적으로 동작하지 않았고, 에러 메시지와 지원되는 기능을 확인한 결과 SQLite 기반 환경이라는 것을 확인하였다.

SQLite는 MySQL과 지원하는 함수와 시스템 테이블 구조가 다르기 때문에 이후 SQLite 기준으로 접근하였다.


스키마 정찰

데이터베이스 내부 구조를 확인하기 위해 SQLite의 시스템 테이블인 sqlite_master를 조회하였다.

SELECT sql FROM sqlite_master;

확인 결과 일반적인 게시판 관련 테이블만 존재했고, FLAG와 직접적으로 연결되는 테이블은 찾지 못하였다.


결정적 단서

DB 내부에서 FLAG 정보를 찾지 못해 추가적으로 사용 가능한 함수 목록을 확인하였다.

그 과정에서 xp_cmdshell이라는 수상한 함수를 발견하였다.

일반적으로 xp_cmdshell은 Microsoft SQL Server에서 운영체제 명령어를 실행하기 위한 기능이다.

하지만 이번 문제에서는 SQLite 환경임에도 해당 함수가 존재했고, 문제 제작자가 추가한 커스텀 함수 형태로 제공한 것으로 판단하였다.

즉 SQL Injection을 통해 데이터베이스 영역을 넘어 OS 명령 실행까지 이어질 수 있는 구조였다.


OS Command Execution

xp_cmdshell을 통해 운영체제 명령 실행이 가능한 것을 확인하고 FLAG 파일 위치를 확인하려 했다.

먼저 디렉터리 구조를 확인하기 위해 다음 명령을 실행하였다.

ls -la

하지만 일부 명령어는 필터링되어 실행되지 않았다.

command not allowed

라는 메시지를 확인했고, 명령어 필터가 존재하는 것을 알 수 있었다.

ls, find와 같은 명령어 사용이 제한되어 있었기 때문에 예상되는 경로에 직접 접근하는 방식으로 FLAG 파일을 찾았다.

cat /예상경로/flag.txt

여러 위치를 확인한 끝에 FLAG 값을 획득할 수 있었다.


공격 흐름 정리

이번 문제의 전체 공격 흐름은 다음과 같다.

SQL Injection 발생

컬럼 개수 확인

출력 위치 확인

DBMS 종류 확인(SQLite)

스키마 정찰

커스텀 함수 발견(xp_cmdshell)

OS Command Execution

FLAG 획득

결론

이번 문제를 통해 SQL Injection은 단순히 특정 페이로드 하나를 입력해서 해결하는 취약점이 아니라, 애플리케이션이 사용하는 SQL 구조와 환경을 분석하는 과정이 중요하다는 것을 다시 확인하였다.

특히 이번 문제에서는 SQL Injection 이후에도 DB 내부 정보만 확인하는 것이 아니라, 사용 가능한 함수와 추가적인 공격 가능성을 분석하면서 OS Command Execution까지 이어갈 수 있었다.

SQL Injection 문제에서는 입력 필터 우회 방법뿐 아니라, 공격 성공 이후 어떤 기능으로 확장할 수 있는지 찾는 과정이 중요하다고 생각한다.

단순히 데이터 조회에서 끝나는 것이 아니라 상황에 따라 파일 접근, 명령 실행, 추가적인 권한 획득 등 다른 공격 단계로 이어질 수 있기 때문에 전체적인 공격 흐름을 이해하는 것이 중요하다.

원본 · velog.io