취약점 개요
CVE-2019-13288 은 xpdf 3.02 버전에서 Parser::getObj()함수 (Parser.cc) 에서 발생하는 무한 재귀 취약점으로
조작된 PDF 파일이 Parser::getObj() 함수의 무한 재귀를 유발하여 스택 메모리 고갈 → 프로그램 크래시 (DoS) 를 일으키는 취약점이다.
환경 구성
먼저 퍼징 타겟인 xpdf를 빌드한다.
wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gz
tar -xvzf xpdf-3.02.tar.gz
cd xpdf-3.02
make clean
# 디버그 + 최적화 비활성화
CFLAGS="-g -O0" CXXFLAGS="-g -O0" ./configure --prefix="$(pwd)/install/"
make
make install
또 퍼징에 이용할 몇 가지 PDF 예제를 다운로드한다.
wget https://github.com/mozilla/pdf.js-sample-files/raw/master/helloworld.pdf
wget http://www.africau.edu/images/default/sample.pdf
wget https://www.melbpc.org.au/wp-content/uploads/2017/10/small-example-pdf-file.pdf
Fuzzing
AFL 로 퍼징하기 위해서는 afl-clang-fast 컴파일러를 사용하여 xpdf를 빌드해야한다.
make clean
CC=afl-clang-fast \
CXX=afl-clang-fast++ \
CFLAGS="-g -O0" \
CXXFLAGS="-g -O0 " \
./configure --prefix="$(pwd)/install/"
make
make install
이제 다음 명령어를 사용하여 퍼저를 실행할 수 있다.
afl-fuzz -i ./pdf_examples/ -o ./out/ -s 123 -- ./xpdf-3.02/install/bin/pdftotext @@ ./output
- -i ./pdf_examples: 입력 디렉토리 - 시드(seed) 파일들이 있는 폴더. 퍼저가 이 파일들을 변형(mutate)하여 테스트 케이스 생성
- -o ./out: 출력 디렉토리 - 퍼징 결과 저장 위치. 크래시, 큐, 통계 등이 저장됨
- -s 123: 시드 값 - 난수 생성기의 고정 시드. 재현 가능한 결과를 위해 사용
- --: 구분자 - 퍼저 옵션과 타겟 프로그램 명령어를 구분
- @@: 입력 파일 플레이스홀더 - AFL이 생성한 테스트 케이스 파일 경로로 대체됨
- ./output: pdftotext의 출력 파일 (변환된 텍스트 저장 위치)

Crash 파일 확인
├── README.txt
├── id:000000,sig:11,src:001081,time:2065167,execs:1462771,op:havoc,rep:1
├── id:000001,sig:11,src:002390,time:2784156,execs:1969696,op:havoc,rep:3
├── id:000002,sig:11,src:002571,time:2974341,execs:2105956,op:havoc,rep:2
├── id:000003,sig:11,src:002784,time:3187085,execs:2236849,op:havoc,rep:3
├── id:000004,sig:11,src:002784,time:3200235,execs:2244863,op:havoc,rep:3
├── id:000005,sig:11,src:001777,time:4076937,execs:2808204,op:havoc,rep:2
├── id:000006,sig:11,src:003116,time:26649130,execs:3479217,op:havoc,rep:2
└── id:000007,sig:11,src:003116,time:26650356,execs:3479430,op:havoc,rep:1
8개의 crash 파일이 발견되었다.
id:000000,sig:11,src:001081,time:2065167,execs:1462771,op:havoc,rep:1
| 필드 | 값 | 의미 |
| id | 000000 | 크래시 고유 ID |
| sig | 11 | SIGSEGV (Segmentation Fault) |
| src | 001081 | 원본 시드 파일 ID |
| time | 2065167 | 발견 시간 (ms, 약 34분) |
| execs | 1462771 | 발견까지 실행 횟수 |
| op | havoc | 사용된 변형 전략 |
| rep | 1 | 반복 횟수 |
Crash 재현 및 디버깅
다음 crash 파일을 재현하는 과정에서 Parser::getObj 무한 재귀 패턴을 발견했다.
gdb --args ./xpdf-3.02/install/bin/pdftotext './out/default/crashes.2025-12-15-11:19:56/id:000001,sig:11,src:002390,time:2784156,execs:1969696,op:havoc,rep:3' ./output

다음과 같이 호출 스택이 무한재귀로 반복되는 것을 확인할 수 있었다.
AddressSanitizer 를 사용하여 xpdf 를 재빌드하고 다시 실행해보았다.
make clean
CC=afl-clang-fast \
CXX=afl-clang-fast++ \
CFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer" \
CXXFLAGS="-g -O0 -fsanitize=address -fno-omit-frame-pointer" \
LDFLAGS="-fsanitize=address" \
./configure --prefix="$(pwd)/install/"
make
make install

- ==218701==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc5da1cfd8
- 오류 유형: stack-overflow
- 원인: Parser::getObj() 반복 호출로 인한 무한 재귀
취약점 패치
xpdf 취약점 패치 로그를 보면 4.02 버전에서 패치되었다고 되어있다.
