공부/Pwnable

[Fuzzing 101] Exercise 2

현생준비중 2024. 4. 2. 00:18

Fuzzing 101 - Exercise 2

목표

  • 외부 어플리케이션을 이용해 라이브러리 퍼징해보기
  • afl-clang-lto을 사용해서 afl-clang-fast보다 더 빠르게, 더 좋은 결과를 얻기
  • GDB 대신 Eclipse IDE 사용해보기

Target

  • libexif 0.6.14
    • 어떤 프로그램인가?
      exif 정보들을 편하게 파싱할 수 있도록 도와주는 라이브러리
    • 어떤 취약점인가?
      • CVE-2009-3895
        libexif 0.6.18의 libexif/exif-entry.c에 있는 exif_entry_fix 함수(일명 태그 수정 루틴)에서 발생하는 Heap Buffer overflow는 잘못된 EXIF 이미지를 통해 공격자가 서비스 거부를 일으키거나 가능하다면 RCE가 발생합니다.
      • CVE-2012-2836
        0.6.21 버전 이전의 EXIF 태그 파싱 라이브러리(일명 libexif)의 exif-data.c에 있는 exif_data_load_data 함수는 이미지 내의 잘못된 EXIF 태그를 통해 원격 공격자가 서비스 거부(범위를 벗어난 읽기)를 일으키거나 가능하면 프로세스 메모리에서 민감한 정보를 얻을 수 있게 합니다.
    • 전략
      libexif는 이름에서도 알 수 있듯이 라이브러리인데, 이걸 Fuzzing 하려면 라이브러리 내의 함수를 호출해야 가능하다. 그래서 외부 어플리케이션을 사용하는 것!
      찾다보니 exif를 설치해서 사용하면 되는듯 하다. 친절하게 README에 있다.

가이드

  1. Find an interface application that makes use of the libexif library
  2. Create a seed corpus of exif samples
  3. Compile libexif and the chosen application to be fuzzed using afl-clang-lto
  4. Fuzz libexif until you have a few unique crashes
  5. Triage the crashes to find a PoC for each vulnerability
  6. Fix the issues

Build & Test

1. libexif Build
    ```
    // 많은 삽질 끝에 패키지가 설치하다는 걸 하나씩 설치했는데, 솔루션에 다 나와있었다
    sudo apt-get install autopoint libtool gettext libpopt-dev
    autoreconf -i
    CC=afl-clang-lto ./configure --enable-shared=no 
    make
    sudo make install
    ```


    마지막에 에러가 뜨긴 했으나 상관 없을 것 같다.

2. exif Build
    ```
    wget https://github.com/libexif/exif/releases/download/exif-0_6_22-release/exif-0.6.22.tar.gz
    tar -xvf exif-0.6.22.tar.gz
    autoreconf -i
    CC=afl-clang-lto ./configure --enable-shared=no 
    make
    sudo make install
    ```


    최신 버전은 에러가 뜨면서 빌드가 안된다.
    버전을 내려보자!

    ```
    wget https://github.com/libexif/exif/archive/refs/tags/exif-0_6_15-release.tar.gz
    tar -xvf exif-0_6_15-release.tar.gz
    autoreconf -i
    CC=afl-clang-lto ./configure
    make
    sudo make install
    ```


    에러도 없고 깔끔하다!

3. Test
    테스트를 위해서는 exif 태그가 있는 사진들을 들고와야 한다.
    ```
    wget https://github.com/ianare/exif-samples/archive/refs/heads/master.zip
    unzip master.zip
    ```

Fuzzing

```
afl-fuzz -i ~/fuzzing_libexif/exif-samples-master/jpg/ -o ~/fuzzing_libexif/out/ -s 123 -- exif @@
```

결과

Fuzzing Result

분석

GDB 대신 Eclipse 써보기

  • 설치 및 설정
    이클립스는 무겁다는 생각이 많이 들어서 사용하기 싫긴 하지만 해보자
    공식 홈페이지에서 다운로드하고 설치하면 된다.exif를 이용해서 디버깅을 해야하니 [New] -> [Makefile Project with Existing Code]를 선택 후 exif 소스코드가 있는 폴더를 선택한다.
    그 후엔 [Run] -> [Debug Configurations]에서 Argument를 설정해주자

  • 이 화면이 나오면 C/C++을 택 해주자
  • 디버깅

    첫 진입점에 break point가 자동으로 설정되어있으며 Resume으로 진행시키면 Crash가 발생하는 곳에서 멈춘다.
    exif_get_short를 호출하는 곳인데 여기에 브레이크 포인트를 찍고 확인해보자exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);에서 break point를 찍고 ds 값을 확인했다.
    해당 함수 내부에서 ds가 1336이므로, exif_data_load_data에서 사용되는 ds의 값은 1342(0x53E)이다.
    d는 73(0x49)였으므로 exif_data_load_data에서 사용되는 d의 값은 67(0x43)이다.
    offset을 적당히 수정하니 조건문에서 통과가 안되고 프로그램이 끝나는데,
    [31m'/home/paka/fuzzing_libexif/out3/default/crashes/crash2' does not contain EXIF data! 라고 뜬다.
  • Unsigned Integer Overflow를 감지해서 적절하게 조치해주면 될 것 같다.
  • exif_get_short에 들어가는 모든 값을 찾았다!

  • 해당 시점에서 offset의 값은 4294967295 = 0xffffffff이다.
    상식적으로 위의 조건문에서 넘어오면 안될 값으로 보이는데 ds 값을 확인해보자.
  • 대부분의 crash가 Little Endian, Big Endian으로 변환하는 과정에서 발생한다.
  • 패치

    offset 값을 검사하는 조건이 하나 더 추가 되었다.
+--------------------------------+
| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
+--------------------------------+     see [instrumentation/README.lto.md](instrumentation/README.lto.md)
    |
    | if not, or if the target fails with LTO afl-clang-lto/++
    |
    v
+---------------------------------+
| clang/clang++ 6.0+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
+---------------------------------+     see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
    |
    | if not, or if the target fails with LLVM afl-clang-fast/++
    |
    v
 +--------------------------------+
 | gcc 5+ is available            | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast)
 +--------------------------------+    see [instrumentation/README.gcc_plugin.md](instrumentation/README.gcc_plugin.md) and
                                       [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
    |
    | if not, or if you do not have a gcc with plugin support
    |
    v
   use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)

분석 다하고 놓친게 있나 찾아봤는데, 설치된 버전에 따라서 Fuzzing에서 사용되는 도구를 다르게 가져갈 수 있다.

'공부 > Pwnable' 카테고리의 다른 글

[Fuzzing 101] Exercise 1  (1) 2024.03.25
[Fuzzing 101] 사전 준비  (0) 2024.03.15
pwntools 사용법 #1  (0) 2022.01.15