[Fuzzing 101] 퍼징으로 1-day 취약점 분석하기(libexif)

들어가며

libexif는 exif을 파싱하는 라이브러리이다. libexif 0.6.14 에서 발생하는 CVE-2009-3895, CVE-2012-2836을 분석한다.

CVE-2009-3895는 올바르지 않은 EXIF 이미지에서 발생하는 힙 버퍼 오버플로우 취약점이다. 힙 데이터 영역에서 발생하는 버퍼 오버플로우의 한 종류이며, 동적 메모리 할당(alloc)과 해제(free)와 관련있다.

공격자는 공격 포인트를 이용하여 응용프로그램이 실행될 때 임의 코드를 삽입하여 실행시킬 수 있다.

CVE-2012-2836는 조작된 EXIF 태그가 있는 이미지를 통해 발생할 수 있는 OOB(Out of Bounds Read) 취약점이다. OOB는 프로그램이 의도한 버퍼의 끝을 지나거나 시작 전의 데이터를 읽을 때 발생하는 취약점이다.

공격자는 서비스 거부(DoS)를 발생시키거나, 중요정보를 메모리에서 탈취할 수 있다.

준비

1-day 실습이므로 취약점이 발생했던 같은 환경을 준비한다. 또는 다음의 내용을 학습할 수 있다.

다음의 내용을 학습한다.

  • 외부 프로그램 실행을 통한 라이브러리 퍼징 방법
  • afl-clang-lto를 사용하여 더 빠른 퍼징
  • GDB 대신 Eclipse IDE를 사용한 디버깅

Download and Build

1. 대상 프로그램 다운 및 빌드

cd $HOME
mkdir fuzzing_libexif && cd fuzzing_libexif/
wget https://github.com/libexif/libexif/archive/refs/tags/libexif-0_6_14-release.tar.gz
tar -xzvf libexif-0_6_14-release.tar.gz
cd libexif-libexif-0_6_14-release/
sudo apt-get install autopoint libtool gettext libpopt-dev
autoreconf -fvi ./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/"
make
make install

2. libexif는 라이브러리이므로 이 라이브러리를 사용하는 프로그램을 이용하여 퍼징해야 한다. exif command line 이라는 프로그램을 이용하여 퍼징을 진행한다.

cd $HOME/fuzzing_libexif
wget [https://github.com/libexif/exif/archive/refs/tags/exif-0_6_15-release.tar.gz](https://github.com/libexif/exif/archive/refs/tags/exif-0_6_15-release.tar.gz)
tar -xzvf exif-0_6_15-release.tar.gz

cd exif-exif-0_6_15-release/
autoreconf -fvi
./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig
make
make install

 

설치가 완료되었다면 다음 명령어로 확인할 수 있다.

$HOME/fuzzing_libexif/install/bin/exif

exif 정상 실행 결과

corpus 생성

corpus는 퍼징을 위한 샘플 데이터셋을 의미한다.

exif 이미지 샘플을 이용하여 퍼징을 진행한다. github의 이미지들을 이용한다.

cd $HOME/fuzzing_libexif wget https://github.com/ianare/exif-samples/archive/refs/heads/master.zip unzip master.zip

압축을 풀었다면 exif 바이너리를 실행시켜서 파일의 정보를 읽을 수 있다.

$HOME/fuzzing_libexif/install/bin/exif $HOME/fuzzing_libexif/exif-samples-master/jpg/Canon_40D_photoshop_import.jpg

Afl-clang-lto instrumentation

afl-clang-lto를 컴파일러로 libexif를 빌드한다.

rm -r $HOME/fuzzing_libexif/install
cd $HOME/fuzzing_libexif/libexif-libexif-0_6_14-release/
make clean
export LLVM_CONFIG="llvm-config-11"
CC=afl-clang-lto ./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/"
make
make install

cd $HOME/fuzzing_libexif/exif-exif-0_6_15-release
make clean
export LLVM_CONFIG="llvm-config-11"
CC=afl-clang-lto ./configure --enable-shared=no --prefix="$HOME/fuzzing_libexif/install/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig
make
make install

afl-clang-fast 대신 afl-clang-lto를 사용했다.

afl-clang-lto는 LTO모드를 사용한다. 이 모드는 AFL 퍼저에서 가장 빠르고 넓은 커버리지를 얻을 수 있다.

https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.lto.md

LTO 모드에서 빌드에 실패한 경우 afl-clang-fast 모드를 사용할 수 있다. LLVM 모드를 사용하며 afl-gcc나 afl-clang 보다 빠른 속도이다.

자세한 내용은 학습이 더 필요하며, AFL 공식 github에 자세한 설명이 되어 있다.

Fuzzing

afl-fuzz -i $HOME/fuzzing_libexif/exif-samples-master/jpg/ -o $HOME/fuzzing_libexif/out/ -s 123 -- $HOME/fuzzing_libexif/install/bin/exif @@

Fuzzing!

시간이 지나면 몇가지 크래시를 확인할 수 있다.

Triage

크래시를 분석한다. 앞서서는 gdb를 사용했지만 이번에는 eclipse를 이용하여 분석한다.

https://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/2021-03/R/eclipse-cpp-2021-03-R-linux-gtk-x86_64.tar.gz

다운받고 의존성 패키지를 설치한다.

sudo apt install default-jdk
tar -xzvf eclipse-cpp-2021-03-R-linux-gtk-x86_64.tar.gz

설치된 경로에서 실행했다면, 소스코드를 import 해야한다. File > Import > C/C++ > “Existing code as makefile project”

“Linux GCC” 선택 > exif 소스코드 폴더 로드

디버그 파라미터 설정을 위해 Run > Debug Configuration > C/C++ Application 더블클릭 > 아래와 같이 내용 채우기

Parameter 탭, 크래시가 발생한 파일을 인자로 지정

디버깅을 진행하다보면 seg fault가 난 지점에서 프로그램이 종료되는 것을 확인할 수 있다.(01번파일에서 크래시 재현이 안되서 00파일로 변경)

분석해보면 파일의 offset에서 불러오는 ds의 값의 검증을 제대로 하지 않아 발생한 버퍼 오버플로우이다.

Fix Bug

공식 버그 패치는 다음과 같다.

 

Fix a buffer overflow on corrupted JPEG data · libexif/libexif@00986f6

An unsigned data length might wrap around when decremented below zero, bypassing sanity checks on length. This code path can probably only occur if exif_data_load_data() is called directly by the a...

github.com


오류 및 부족한 내용 알려주세요!

반응형