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

들어가며

1-day 익스플로잇 실습을 진행한다. CVE-2019-13288 취약점이며 Xpdf라는 pdf 뷰어에서 발생한 Dos 취약점이다. 자세한 취약점 정보는 https://www.cvedetails.com/cve/CVE-2019-13288/에서 볼 수 있으며, 관련된 취약점 설명은 https://cwe.mitre.org/data/definitions/674.html 에서 확인할 수 있다.

정리하면, 프로그램에서 호출된 각 함수가 스택에 스택 프레임을 할당하기 때문에, 함수를 너무 많이 재귀적으로 호출하면 스택 메모리 부족과 충돌로 이어질 수 있는 취약점이다.

준비

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

Download and Build

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

cd $HOME
mkdir fuzzing_xpdf && cd fuzzing_xpdf/

2. 빌드 위한 make와 gcc 다운로드

sudo apt install build-essential

3. Xpdf 3.02 다운로드

wget https://dl.xpdfreader.com/old/xpdf-3.02.tar.gz
tar -xvzf xpdf-3.02.tar.gz

4. 빌드

cd xpdf-3.02
sudo apt update && sudo apt install -y build-essential gcc
./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

5. PDF 예제 파일을 통한 실행 확인

cd $HOME/fuzzing_xpdf
mkdir pdf_examples && cd pdf_examples
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

6. pdfinfo 바이너리를 통한 테스트

$HOME/fuzzing_xpdf/install/bin/pdfinfo -box -meta
$HOME/fuzzing_xpdf/pdf_examples/helloworld.pdf

AFL++ 설치

1. 의존성패키지 설치

sudo apt-get update
sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev

2. AFL++ 빌드 checkout

cd $HOME
git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
export LLVM_CONFIG="llvm-config-11"
make distrib
sudo make install

3. afl-fuzz

Fuzzing 101

AFL은 커버리지 가이드 퍼저로, 새로운 실행 경로와 잠재적인 버그를 발견하기 위해 변형된 각 입력에 대한 커버리지 정보를 수집한다는 것을 의미한다. 소스 코드를 사용할 수 있을 때 AFL은 계측(instrumentation)을 사용할 수 있으며, 각 기본 블록(함수, 루프 등)의 시작 부분에 함수 호출을 삽입할 수 있다.

대상 응용 프로그램에 대한 instrumentation을 활성화하려면 AFL의 컴파일러로 코드를 컴파일해야 한다.

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean

afl-clang-fast 컴파일러를 이용하여 xpdf를 빌드한다.

export LLVM_CONFIG="llvm-config-11"
CC=$HOME/AFLplusplus/afl-clang-fast CXX=$HOME/AFLplusplus/afl-clang-fast++ ./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

이제 다음 명령어를 이용해서 fuzzer를 실행시킬 수 있다.

afl-fuzz -i $HOME/fuzzing\_xpdf/pdf\_examples/ -o $HOME/fuzzing\_xpdf/out/ -s 123 -- $HOME/fuzzing\_xpdf/install/bin/pdftotext @@ $HOME/fuzzing\_xpdf/output

각각의 옵션에 대한 설명은 다음과 같다.

  • -i : 입력 케이스가 위치한 경로
  • -o : 퍼저가 변환한 파일을 저장할 경로
  • -s : 정적 랜덤 시드(빠른 재현을 위해 -123 사용)
  • @@ : AFL이 각 입력 파일 이름으로 대체할 자리 표시자

이렇게 실행하게 되면 fuzzer는 각각의 다른 입력 파일을 생성해서 다음의 명령을 실행하는 것이다.

$HOME/fuzzing\_xpdf/install/bin/pdftotext <input-file-name> $HOME/fuzzing\_xpdf/output

"Hmm, your system is configured to send core dump notifications to an external utility..." 에러 발생 시 다음과 같이 실행한다.

sudo su
echo core >/proc/sys/kernel/core_pattern
exit

퍼징을 진행하다보면 크래시가 발생하고 크래시가 발생한 파일은 $HOME/fuzzing_xpdf/out/ 경로에 저장된다. Ctrl+C를 이용하여 퍼저를 중지할 수 있고 경로에 들어가서 파일을 분석해볼 수 있다.

out 경로에는 크래시가 발생한 파일들의 목록을 확인할 수 있다.

~/fuzzing\_xpdf/install/bin/pdftotext ‘~/fuzzing\_xpdf/out/default/crashes/<결과파일명>’ ~/fuzzing\_xpdf/output

명령어로 실행했을 때 Segmentation fault와 함께 프로그램이 종료되는 것을 확인할 수 있다.

Triage

gdb를 이용하여 크래시를 분석해 본다.

먼저, 디버그 정보 및 심볼릭 링크 정보를 얻기 위해 Xpdf를 다시 빌드해야 한다.

rm -r $HOME/fuzzing_xpdf/install
cd $HOME/fuzzing_xpdf/xpdf-3.02/
make clean
CFLAGS="-g -O0" CXXFLAGS="-g -O0" ./configure --prefix="$HOME/fuzzing_xpdf/install/"
make
make install

gdb --args $HOME/fuzzing\_xpdf/install/bin/pdftotext $HOME/fuzzing\_xpdf/out/default/crashes/<your\_filename> $HOME/fuzzing\_xpdf/output

gdb 실행 후 분석한다.

$run과 $bt (back trace) 명령어를 보면 많은 재귀적인 Parser::getObj 호출을 볼 수 있다. CVE-2019-13288 의 설명과 같이 GDB 분석결과가 일치하는 것을 확인할 수 있다.

반응형