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

들어가며

LibTIFF라는 이미지 라이브러리를 퍼징한다. LiBTIFF 4.0.4에서 발생하는 CVE-2016-9297을 분석한다. 그리고 발견한 크래시에서 코드 커버리지를 분석한다.

CVE-2016-9297는 OOB(Out-of-bounds) 취약점이다. 버퍼 범위 바깥의 인덱스에 접근할 때 발생하며, 조작된 TIFF_SETGET_C16ASCII 와 TIFF_SETGET_C32_ASCII 태그 값에서 발생한다.

공격자는 서비스 거부를 발생시키거나 프로세스 메모리에서 의도하지 않은 중요 정보를 탈취할 수 있다.

준비

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

다음의 내용을 학습한다.

  • LCOV를 이용한 코드 커버리지 측정 방법
  • 퍼징의 효율성 증가를 위한 코드 커버리지 데이터 활용 방법

Download and Build

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

cd $HOME
mkdir fuzzing_tiff && cd fuzzing_tiff/
wget https://download.osgeo.org/libtiff/tiff-4.0.4.tar.gz
tar -xzvf tiff-4.0.4.tar.gz
cd tiff-4.0.4/
./configure --prefix="$HOME/fuzzing_tiff/install/" --disable-shared
make
make install

 

2. /bin 폴더 아래에 위치한 tiffinfo 바이너리를 퍼징한다. corpus 입력을 위한 샘플 데이터는 /test/images 폴더에 위치한다.

3. 사용법은 아래와 같다.

$HOME/fuzzing_tiff/install/bin/tiffinfo -D -j -c -r -s -w $HOME/fuzzing_tiff/tiff-4.0.4/test/images/palette-1c-1b.tiff

바이너리 실행 옵션에서 -j -c -r -s -w 등을 부여하였는데 이는 코드 커버리지를 확장하여 버그를 발견할 수 있는 기회를 더 많이 가지도록 한다.

하지만 입력 케이스에 따른 코드 커버리지는 어떻게 측정해야 할까?

Code Coverage

코드 커버리지는 각 코드 행이 트리거되는 횟수를 보여주는 소프트웨어 메트릭입니다. 코드 커버리지를 사용함으로써 우리는 퍼저가 코드의 어떤 부분에 도달했는지 알 수 있고 퍼지 프로세스를 시각화할 수 있다.

1. 다음의 명령으로 lcov설치

sudo apt install lcov

 

2. libTIFF를 —coverage 플래그와 함께 다시 빌드한다.

rm -r $HOME/fuzzing_tiff/install
cd $HOME/fuzzing_tiff/tiff-4.0.4/
make clean
  
CFLAGS="--coverage" LDFLAGS="--coverage" ./configure --prefix="$HOME/fuzzing_tiff/install/" --disable-shared
make
make install

 

3. 다음의 명령을 이용하여 코드 커버리지 데이터를 수집할 수 있다.

cd $HOME/fuzzing_tiff/tiff-4.0.4/
lcov --zerocounters --directory ./
lcov --capture --initial --directory ./ --output-file app.info
$HOME/fuzzing_tiff/install/bin/tiffinfo -D -j -c -r -s -w $HOME/fuzzing_tiff/tiff-4.0.4/test/images/palette-1c-1b.tiff
lcov --no-checksum --directory ./ --capture --output-file app2.info
  • lcov —zerocounters —directory ./ : 이전 카운터 초기화
  • lcov —capture —initial —directory ./ —output-file app.info : 모든 측정된 라인에 대해 커버리지가 0인 “기준” 커버리지 데이터 파일을 반환
  • $HOME/fuzzing_tiff/install/bin/tiffinfo -D -j -c -r -s -w $HOME/fuzzing_tiff/tiff-4.0.4/test/images/palette-1c-1b.tiff : 분석을 위한 바이너리 실행, 다양한 입력값을 이용하여 여러번 실행할 수 있다.
  • lcov --no-checksum --directory ./ --capture --output-file app2.info : 현재 적용 범위 상태를 app2.info 파일에 저장

4. HTML 형식으로 출력(리포트)을 확인할 수 있다.내용을 확인하면 각각의 라인이 몇 번씩 실행되었는지 확인할 수 있다.

genhtml --highlight --legend -output-directory ./html-coverage/ ./app2.info

Fuzzing

ASAN을 활성화한 상태로 libtiff를 컴파일하고 퍼징한다.

기존에 컴파일된 파일을 정리한다.

rm -r $HOME/fuzzing_tiff/install
cd $HOME/fuzzing_tiff/tiff-4.0.4/
make clean

 

AFL_USE_ASAN=1 옵션과 함께 make

export LLVM_CONFIG="llvm-config-11"
CC=afl-clang-lto ./configure --prefix="$HOME/fuzzing_tiff/install/" --disable-shared
AFL_USE_ASAN=1 make -j4
AFL_USE_ASAN=1 make install

 

FUZZ!

afl-fuzz -m none -i $HOME/fuzzing_tiff/tiff-4.0.4/test/images/ -o $HOME/fuzzing_tiff/out/ -s 123 -- $HOME/fuzzing_tiff/install/bin/tiffinfo -D -j -c -r -s -w @@

Triage

ASan으로 trace한 결과는 아래와 같다.

 

Bug Fix

공식 패치는 https://github.com/vadz/libtiff/commit/30c9234c7fd0dd5e8b1e83ad44370c875a0270ed 에서 제공한다

 

* libtiff/tif_dirread.c: in TIFFFetchNormalTag(), make sure that · vadz/libtiff@30c9234

values of tags with TIFF_SETGET_C16_ASCII / TIFF_SETGET_C32_ASCII access are null terminated, to avoid potential read outside buffer in _TIFFPrintField(). Fixes http://bugzilla.maptools.org/show_bu...

github.com

 

반응형