
[심층 분석] Snort를 이용한 이미지 파일(GIF) 버퍼 오버플로우 탐지 전략
보안관제 업무를 수행하다 보면 수많은 경보(Alert)를 마주하게 됩니다. 그중에서도 단순히 텍스트 문자열을 탐지하는 것이 아니라, 파일 포맷의 구조적 결함을 이용하는 공격을 탐지해야 할 때가 있습니다. 이러한 공격은 일반적인 시그니처 기반 탐지로는 놓치기 쉽습니다.
본 포스팅에서는 GIF 이미지 파일로 위장한 버퍼 오버플로우(Buffer Overflow) 공격을 탐지하는 Snort 룰을 상세히 분석합니다. 특히 초급 분석가들이 자주 혼동하는 byte_test 옵션과 relative, within 등의 위치 지정자의 정확한 동작 원리를 파헤쳐 보겠습니다.
1. 공격 시나리오: 해커는 왜 GIF 파일을 조작하는가?
버퍼 오버플로우 취약점은 프로그램이 할당된 메모리 공간보다 더 많은 데이터를 쓰려고 할 때 발생합니다. 해커는 이 원리를 이미지 뷰어 프로그램에 적용합니다.
- 거짓 정보 기입: 해커는 GIF 파일 헤더의 너비(Width) 값을 20,000 픽셀 이상으로 조작합니다. (일반적인 4K 해상도가 약 4,000 픽셀임을 감안하면 터무니없이 큰 값입니다.)
- 메모리 할당 유도: 이미지 뷰어는 헤더 정보만 믿고 20,000 픽셀에 해당하는 거대한 메모리 공간을 확보하려 시도하거나, 잘못된 계산으로 엉뚱한 메모리 주소를 참조하게 됩니다.
- 코드 실행: 이 과정에서 프로그램이 비정상 종료(Crash)되거나, 해커가 심어둔 악성 코드가 실행될 수 있는 틈(Shellcode Execution)이 생깁니다.
2. Snort 룰 라인 바이 라인(Line-by-Line) 분석
다음은 해당 공격을 탐지하기 위한 Snort 룰 전문입니다.
msg:"EXPLOIT-GIF Malformed Header Width Overflow";
flow:to_server,established;
content:"|47 49 46 38 39 61|"; depth:6;
byte_test:2, >, 20000, 0, relative, little;
flowbits:set,gif_exploit_attempt; flowbits:noalert;
content:"|3B|"; distance:0; within:1000;
sid:1000555; rev:3;
)
(1) 파일 식별: GIF89a 헤더 확인
16진수 47 49 46 38 39 61은 ASCII 텍스트로 GIF89a입니다. 모든 파일은 고유의 시그니처(Magic Number)를 가지고 있습니다.
- depth:6의 의미: 패킷의 맨 처음부터 정확히 6바이트까지만 검사하라는 뜻입니다. GIF 시그니처는 항상 파일의 맨 앞에 위치하기 때문입니다. 만약
depth가 없다면 Snort는 패킷 전체를 뒤지게 되어 성능 저하를 초래합니다.
(2) 핵심 로직: 비정상적인 너비(Width) 값 검증
이 룰의 핵심이자 많은 분들이 가장 어려워하는 부분입니다.
Q. 왜 하필 2바이트를 읽나요?
GIF 파일 포맷 표준(RFC)에 따르면, 헤더(GIF89a, 6바이트) 바로 뒤에 논리적 화면 너비(Logical Screen Width)가 2바이트 크기로 위치합니다. 즉, 공격자가 조작하는 바로 그 부분입니다.
| 옵션 인자 | 설명 |
|---|---|
| 2 | 검사할 데이터의 크기 (Bytes to convert) |
| > | 비교 연산자 (Greater Than) |
| 20000 | 기준 임계값 (Value to compare against) |
| 0 | 오프셋 (Offset). 여기서는 건너뛰지 않고 바로 읽습니다. |
| relative | [중요] 이전 매칭(content:"GIF89a")이 끝난 지점부터 계산합니다. 이 옵션이 없으면 패킷의 맨 처음(0번지)부터 읽게 되어 엉뚱한 값을 검사하게 됩니다. |
| little | GIF 파일은 데이터를 리틀 엔디안(Little Endian) 방식으로 저장합니다. 예를 들어, 20,000(0x4E20)은 파일 내에 20 4E 순서로 저장됩니다. Snort에게 이를 올바르게 해석하라고 알려주는 옵션입니다. |
(3) 오탐(False Positive) 최소화 전략
Q. 너비가 2만이 넘으면 바로 차단하면 안 되나요?
안 됩니다. 최근에는 전문적인 디자인 작업용으로 초고해상도(8K 이상) 이미지가 전송될 수 있습니다. 단순히 너비가 크다는 이유로 차단하면 정상 업무 트래픽에 영향을 줄 수 있습니다.
따라서, set으로 "의심스러운 파일"이라는 태그만 붙여두고(marking), noalert를 사용하여 관리자에게 불필요한 알람을 보내지 않습니다.
(4) 결정적 증거 확보: 파일 크기와의 모순
이 부분이 공격을 확정 짓는 결정타입니다.
- |3B|: 16진수
0x3B는 GIF 파일의 끝을 알리는 종료 트레일러(Trailer, ;)입니다. - within:1000의 의미: 앞서 검사한 너비 정보(Header)가 나온 직후부터 1,000바이트 이내에 파일이 끝나야 한다는 조건입니다.
"너비가 20,000 픽셀이나 되는 초대형 이미지라면 파일 크기가 수 메가바이트(MB)는 되어야 합니다. 그런데 헤더가 나오자마자 1KB(1000바이트)도 안 돼서 파일이 끝난다? 이는 속이 텅 빈, 공격용으로 조작된 파일임이 확실합니다."
3. 초보 분석가가 자주 범하는 실수 (Troubleshooting)
Snort 룰을 작성하거나 해석할 때 다음 세 가지 실수를 주의해야 합니다.
1) relative 옵션 누락
byte_test를 사용할 때 relative를 빼먹으면, Snort는 패킷의 맨 처음(Offset 0)부터 계산을 시작합니다. 이렇게 되면 GIF 헤더 뒤에 있는 너비 값이 아니라, 엉뚱하게 "GIF89a" 텍스트 자체를 숫자로 변환하여 비교하게 되므로 탐지에 실패합니다.
2) Endian 설정 오류
네트워크 패킷은 기본적으로 빅 엔디안(Big Endian)을 사용하지만, 파일 포맷(GIF, JPEG 등)이나 x86 시스템은 리틀 엔디안(Little Endian)을 사용하는 경우가 많습니다. 분석하려는 대상이 어떤 방식인지(RFC 문서 확인 필요) 정확히 모르면, 20,000(0x4E20)을 8,270(0x204E)으로 잘못 읽는 오류를 범하게 됩니다.
3) flowbits 미사용
복합적인 조건을 단계별로 검사하지 않고 단일 룰로 처리하려다 보면 오탐이 폭증합니다. "너비가 큼" AND "파일이 작음"이라는 두 조건의 인과 관계를 flowbits로 연결하는 습관을 들여야 정교한 탐지가 가능합니다.
4. 결론
이번 포스팅을 통해 단순한 문자열 매칭을 넘어, 바이너리 데이터 분석과 논리적 상관관계를 이용한 고급 탐지 기법을 살펴보았습니다.
보안관제의 수준은 툴 사용법이 아니라, "프로토콜의 구조(Structure)를 얼마나 깊이 이해하고 있는가"에서 결정됩니다. 오늘 다룬 byte_test와 relative 개념을 완벽히 숙지하신다면, GIF뿐만 아니라 다양한 파일 포맷 기반의 공격을 탐지하는 데 큰 무기가 될 것입니다.
'정보보안' 카테고리의 다른 글
| 금융권 필수 보안 시스템, NAC(네트워크 접근 제어) 완벽 해부 (1) | 2025.12.03 |
|---|---|
| 기업 무선 보안의 최후의 보루, WIPS(무선침입방지시스템) 심층 분석 가이드 (1) | 2025.12.03 |
| 보안관제의 핵심 무기, Snort Rule 완전 정복 가이드 (0) | 2025.11.28 |
| 2025년 10월, 윈도우 10 지원 종료에 따른 대응 전략 윈도우11설치 (0) | 2025.11.27 |
| 2025 CSAP 클라우드 보안인증 완벽 가이드 | 개요, 등급, 인증방법, 업체 현황 총정리 (0) | 2025.10.16 |