취약점/Fuzzing101

[Fuzzing101] Exercise 2 - libexif (CVE-2009-3895, CVE-2012-2836)

comalmot_ 2022. 3. 26. 19:47
반응형

안녕하세요, comalmot 입니다.

 

오늘은 Fuzzing101 Exercise 2를 풀어보도록 하겠습니다.

 

지난 Exercise 1이 페이스북에 올렸더니 조회수가 아주 쭉쭉..올라 기분이 너무 좋더라구요~

 

기대에 부응하기 위해 Exercise 2 풀이도 준비해봤습니다...!

 

테스트 환경

Exercise 1을 풀 때와 같습니다.

  • OS : Ubuntu 20.04.2 LTS
  • RAM : 4GB
  • HDD : 32GB
  • VMWare Workstation 16 Pro

오늘 퍼징을 통해 발견할 취약점은 두 개입니다. 

 

CVE-2009-3895

cvedeatils에서 확인한 정보

libexif 0.6.18 버전의 exif-entry.c 파일에 있는 exif_entry_fix 함수에서 발생하는 Heap 기반 Overflow 취약점인 것으로 확인되었으며, DoS 또는 임의 코드를 실행시킬 수 있는 것으로 판명되었습니다.

 

CVE-2012-2836

libexif 0.6.21 이전 버전의 exif-data.c 파일에 있는 exif_data_load_data 함수에서 발생하는 OOB(Out-of-Bounds) Read 취약점입니다. DoS 또는 조작된 경로를 통해 메모리에서 중요한 정보를 얻을 수 있다고 합니다.

 

What will you learn?

  • 외부 응용 프로그램을 사용하여 라이브러리를 퍼징하는 법을 알게된다고 합니다.
  • afl-clang-fast 보다 더 빠르고 더 나은 결과를 제공하는 afl-clang-lto의 사용법을 알게 됩니다.
  • Eclipse IDE를 사용하여 triaging을 위한 GDB Console을 쉽고 인터랙티브하게 사용할 수 있습니다.

이번에도 시드 옵션(-s)는 123으로 고정입니다.

 

Do it yourself!

 

1. libexif 라이브러리를 사용하는 인터페이스 애플리케이션을 찾습니다.

번역기에 돌리다보니 문장이 조금 이상하네요. libexif는 말 그대로 라이브러리입니다. 

libexif 구글 검색결과

따라서 이 라이브러리를 사용하는 프로그램을 찾아야하겠습니다. libexif의 페이지에 들어가보니 exif라는 프로그램이 있었네요. 우선 취약한 버전의 libexif를 빌드한 후에, 해당 프로그램에 적용시켜야겠습니다.

저는 libexif 0.6.18 버전을 빌드할 계획을 짰습니다만, 아래에 있는 삽질기로 인해.. 0.6.14 버전을 빌드하였습니다.

2. exif 샘플의 시드 코퍼스를 생성합니다.

시드 코퍼스(Seed Corpus)라는 말이 무슨 말인지 몰라서 검색을 해보았습니다.

https://com24everyday.tistory.com/355

 

퍼징의 이해_장대희

퍼징이란 취약점을 찾기 위해 사용하는 기술들의 집합입니다. BOF 라든지 악성코드를 심는 걸 퍼징을 통해 발견합니다. 발표 순서는 다음과 같았습니다. 1. 기본 개념 - 버그(Bug)와 퍼징(Fuzzing)의

com24everyday.tistory.com

어이없게도 Input이었네요.. 제가 이런 것도 모르고 이걸 공부하고 있다니.. 반성해야겠습니다.

 

이제 많은 Input Case를 생성하라는 말이겠지요.

우선 인터넷에 있는 예제를 몇 가지 가져오기로 했습니다. 샘플들을 찾다가, 여기 에 있는 jpg 파일들을 가져오기로 했습니다.

 

그 전에 EXIF가 뭔지 알아야하겠죠?

EXIF는 EXchangable Image File format의 약자로, 디지털 카메라에서 이용되는 이미지 파일 포맷이며, 이 데이터는 JPEG, TIFF 6.0, RIFF에서 지원됩니다. 

 

크게 분류하여 세 가지의 정보를 표현하는데요, 아래와 같습니다.

  • 날짜와 시간 정보
  • 카메라 설정
  • 저작권 정보에 대한 설명

예제 파일 중 하나의 속성을 보겠습니다. 이렇게 카메라 모델 등이 나오는 것을 확인하실 수 있습니다.

자세한 정보는 이 링크를 참고하세요.

 

자, 이제 EXIF도 알았으니, 빌드를 시작해보겠습니다.

 

afl-clang-lto를 사용해서 빌드하기 전에, 먼저 테스트용으로 그냥 빌드해볼 것 입니다.

 

+후.. sourceforge에서 다운받은 tar 파일로 make 하면 오류가 범벅이네요.. ㅠㅠ

 

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-0_6_14-release.tar.gz
./configure --perfix="$HOME/fuzzing_libexif/install"
make
make install

이렇게 되면 libexif가 빌드된 파일이 $HOME/fuzzing_libexif/install 아래에 있게 됩니다.

 

확인해볼까요?

빌드가 잘 된 모습

네, 빌드가 잘 되었습니다. 

 

이제는 libexif를 사용하는 인터페이스 애플리케이션인 exif를 빌드하겠습니다.

 

exif는 딱 두 가지의 dependency를 요구하는데요, 첫 번째는 우리가 방금 전 빌드했던 libexif이며, 하나는 popt 라는 녀석입니다.

 

popt는 우분투 기준으로 손쉽게 설치할 수 있습니다. 아래 명령을 입력합니다.

sudo apt-get install autopoint libtool gettext libpopt-dev

 

exif도 마찬가지로 tar.gz의 압축파일 형태로 다운받은 것을 풀어 빌드해야 합니다. 이 링크 에서 다운로드 받으실 수 있습니다.

 

이제 아래 명령을 입력하여 빌드를 시작합니다.

./configure --prefix="$HOME/fuzzing_libexif/install_exif/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig
make
make install

PKG_CONFIG_PATH 에는 아까 빌드했던 libexif의 pkgconfig 디렉토리의 경로를 지정해주면 됩니다. 이러면 원하는 버전의 libexif을 exif 애플리케이션이 사용하도록 할 수 있습니다.

 

이제 테스트해보겠습니다. 잘 실행되는지 볼까요?

네, 잘 실행됩니다. 이미지의 EXIF 정보도 가져올 수 있는지 확인해보도록 하겠습니다.

 

저는 이 링크 의 예제를 이용하였습니다.

 

잘 나오는 군요, 빌드가 잘 되었습니다.

 

3. afl-clang-lto를 사용하여 libexif와 퍼징할 응용프로그램을 컴파일합니다.

이제 afl-clang-lto를 사용하여 다시 한 번 빌드할 것입니다. 

저번 Exercise 1에서는 afl-clang-fast를 사용하여 빌드를 했었습니다(디버깅 옵션을 포함하여).

 

이번에도 똑같이 빌드해주겠습니다.

 

빌드 시작 전에, 기존에 빌드된 libexif와 exif 애플리케이션을 삭제할 것입니다. 아래 명령을 입력합니다.

rm -r $HOME/fuzzing_exif/install
rm -r $HOME/fuzzing_exif/install_exif

cd $HOME/fuzzing_exif/libexif-0.6.18
make clean

cd $HOME/fuzzing_exif/exif-0.6.22
make clean

이로서 빌드한 libexif와 exif 애플리케이션을 삭제하였습니다.

 

이제 afl-clang-lto 를 사용하여 libexif와 exif 애플리케이션을 빌드하겠습니다.

아래 명령을 입력합니다.

cd $HOME/fuzzing_libexif/libexif-0.6.14
export LLVM_CONFIG="llvm-config-12"
autoreconf -fvi
CC=$HOME/AFLplusplus/afl-clang-lto ./configure --prefix="$HOME/fuzzing_libexif/install/" --enable-shared=no
make
make install

cd $HOME/fuzzing_libexif/exif-0.6.15
export LLVM_CONFIG="llvm-config-12"
autoreconf -fvi
CC=$HOME/AFLplusplus/afl-clang-lto ./configure --prefix="$HOME/fuzzing_libexif/install/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig --enable-shared=no
make
make install

 

이제 퍼징을 해보겠습니다.

 

4. 몇 가지 saved crashes가 나올때까지 libexif를 퍼징합니다.

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

이제 실행합니다.

 

삽질기1 (configure에 --enable-shared=no 옵션 추가)

갑자기 발생한 오류

No instrumentation detected라는 오류가 나왔습니다. 많이 당황스럽네요.

 

결국엔 빌드 과정을 다시 찾아보았습니다. ㅠㅠ

 

cd $HOME/fuzzing_libexif/libexif-0.6.18
export LLVM_CONFIG="llvm-config-11"
CC=$HOME/AFLplusplus/afl-clang-lto CXX=$HOME/AFLplusplus/afl-clang-lto++ ./configure --prefix="$HOME/fuzzing_libexif/install/" --enable-shared=no
make
make install

cd $HOME/fuzzing_libexif/exif-0.6.22
export LLVM_CONFIG="llvm-config-11"
CC=$HOME/AFLplusplus/afl-clang-lto CXX=$HOME/AFLplusplus/afl-clang-lto++ ./configure --prefix="$HOME/fuzzing_libexif/install_exif/" PKG_CONFIG_PATH=$HOME/fuzzing_libexif/install/lib/pkgconfig --enable-shared=no
make
make install

--enable-shared=no 옵션을 configure에 주니 해결되었습니다.

 

 

이제 퍼징을 시작해봅시다!

Fuzzing!

1시간 정도(딴짓하면서..) 돌렸습니다. 18개의 saved crashes가 등장했습니다.

이제 crashes 폴더를 들어가서 확인해보도록 합시다!

Crashes 실행

Crash를 실행하니 realloc() 에서 invalid next size라는 오류, Aborted라는 문자열이 출력됩니다.

 

gdb로 열어보면 아래와 같은 모습이네요.

이제 본격적으로 분석에 들어가 봅시다.

5. Crash를 분류하여 각 취약점에 대한 PoC를 찾습니다.

어떻게 보면 제일 어려운 부분입니다. 이제부터 진짜 분석 시작입니다.

 

우선 bt를 통해서 backtrace합니다.

Exercise 1에 비해 굉장히 간단합니다. 이 문제 만든 분들은 어쩌면 수많은 backtrace들에 처음부터 단련되도록 하신 걸수도 있겠다는 생각이 드네요. ㅋㅋㅋㅋㅋ

 

잠깐 돌아가서, 위에서 언급한 취약점들을 다시 한 번 봅시다.

 

이번 포스트에서는 CVE-2009-3895, CVE-2012-2836 이 두 가지의 취약점을 언급하였습니다.

 

각각의 취약점이 있는 부분은 아래와 같습니다.

 

  • exif_data_load_data (CVE-2009-3895, Heap-based Overflow)
  • exif_entry_fix (CVE-2012-2836, OOB Read)

이제 Crash들을 분류한 뒤에 분석을 시작해보도록 하겠습니다.

 

삽질기 2 (libexif 버전 0.6.14를 사용해야하는데 0.6.18을 사용함, exif 버전 0.6.15를 사용해야하는데 0.6.22를 사용함)

그런데 문제가 생겼습니다. exif_data_load_data는 분명 Crash가 있는데, exif_entry_fix에서 터지는 Crash가 없습니다....

 

제가 너무 적게 돌렸나요? 다시 한 번 돌려보았습니다.

4시간 돌렸습니다. 근데... 여전히 없어요. libexif 버전이 문제인 것 같아 다시 빌드한 후에 돌려보겠습니다.

 

이럴수가... 없네요 Heap Overflow가.. "또" 다시 빌드해야겠습니다. 확인을 해보니 libexif 0.6.14를 가지고 하는 거였군요... ㅠㅠㅠㅠㅠㅠㅠ 

 

그래서 버전 바꿨는데 이번엔 Heap Overflow만 나오네요.. 대체 뭐지

 

일단 계속 돌렸습니다...

 

삽질기 3 (afl-fuzz에 -D 옵션 활성화)

여러 삽질 후에, Github Security Lab Slack Channel에 들어가서 질문을 해보았습니다.

그랬더니 이 Exercise를 만드신 Antonio Morales님께서 직접 답변을!! 해주시더군요.. ㅠㅠ

 

Antonio Morales님의 답변

최신 버전의 AFL++.. 그러니까 저의 경우(저는 4.01a) 이었습니다. -D 옵션을 활성화해주어야, deterministic mutation이 enable 된다는 이야기였습니다. 이게 안 되어서 다양한 mutation이 안됐던거였고, 그래서 취약점도 제한적으로만 찾을 수 있었습니다.. 예를 들자면 앵거로 푸는 문제를 손으로 풀려고 했달까요... ㅠ

-D 옵션을 활성화한 후의 모습

네, fuzzing strategy yields 카테고리가 활성화가 되었습니다.

 

이제 다시 시작입니다.. ㅠㅠ 슬프지만 문제가 해결됐다는 것에 만족합시다..

 

Crash 분석 과정은 시험 기간이 끝난 후 업로드하겠습니다.

 

 

반응형

'취약점 > Fuzzing101' 카테고리의 다른 글

[Fuzzing101] Exercise 1 - Xpdf (CVE-2019-13288)  (2) 2022.03.14