Fuzzing101系列 Exercise 1 - Xpdf

 序言

 Fuzzing101系列包含針對10 個真實目標的10個練習,在練習中一步一步學習Fuzzing技術的知識。

 模糊測試(Fuzzing/Fuzz)是一種自動化軟件測試技術,它基於爲程序提供隨機或變異的輸入值並監視它的異常和崩潰。

 AFL、libFuzzer 和 HonggFuzz 是現實世界應用中最多的三個模糊器,這三個都是覆蓋引導的進化模糊器(Coverage-guided evolutionary fuzzer)。其中

  • 進化(evolutionary)是一種受進化算法啓發的元啓發式方法,它基本上包括通過使用選擇標準(例如覆蓋率)隨時間推移初始子集(種子)的進化和變異。

  • 覆蓋引導(Coverage-guided)是指爲了增加發現新崩潰的機會,覆蓋引導的模糊器收集和比較不同輸入之間的代碼覆蓋率數據,並選擇那些導致新執行路徑的輸入。

 在這個練習中,我們將fuzz Xpdf PDF 查看器。目的是在 XPDF 3.02 中找到 CVE-2019-13288 的崩潰/PoC。

 CVE-2019-13288 是一個漏洞,它可能會通過精心製作的文件導致無限遞歸。由於程序中每個被調用的函數都會在棧上分配一個棧幀,如果一個函數被遞歸調用這麼多次,就會導致棧內存耗盡和程序崩潰。因此,遠程攻擊者可以利用它進行 DoS 攻擊。可以在以下鏈接中找到有關不受控制的遞歸漏洞的更多信息:https://cwe.mitre.org/data/definitions/674.html

 你會學到什麼

 完成本練習後,你將瞭解使用 AFL 進行 fuzz 的基礎,例如:

  • 使用檢測編譯目標應用程序

  • 運行模糊器(afl-fuzz)

  • 使用調試器 (GDB) 對崩潰進行分類

 環境

 所有練習都在 Ubuntu 20.04.2 LTS 上進行了測試。 我強烈建議您使用相同的操作系統版本以避免不同的模糊測試結果,並在裸機硬件而不是虛擬機上運行 AFL,以獲得最佳性能。

 否則,您可以在此處找到 Ubuntu 20.04.2 LTS 鏡像。用戶名爲 fuzz / fuzz

 AFL 使用非確定性測試算法,因此兩個模糊測試會話永遠不會相同。我強烈建議設置一個固定的種子(-s 123),這樣你的模糊測試結果將與本文的結果相似。

 下載並構建目標

 首先爲要進行模糊測試的項目創建一個新目錄:

cd $HOME
mkdir fuzzing_xpdf && cd fuzzing_xpdf/

 爲了完全準備好環境,需要安裝一些額外的工具(make 和 gcc)

sudo apt install build-essential

 下載 Xpdf 3.02:

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

 構建 Xpdf:

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

 下面對 Xpdf 進行測試,首先下載一些 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

 使用以下命令測試 pdfinfo 二進制文件:

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

63ba5d42bc70b0a8604079668b0aa6b6.png

 安裝 AFL++

 我們將使用最新版本的 AFL++ fuzzer(https://github.com/AFLplusplus/AFLplusplus)

 安裝依賴項

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

 構建 AFL++

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

 執行afl-fuzz,查看是否安裝成功

6c5ed0fc519a72c6e13a84cfc4516a53.png

 認識 AFL++

 AFL 是一個覆蓋引導的模糊器(coverage-guided fuzzer),這意味着它收集每個變異輸入的覆蓋信息,來發現新的執行路徑和潛在的錯誤。當源代碼可用時,AFL 可以使用插樁(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 表示 AFL + + 將存儲的變異文件的目錄

  • -s 表示要使用的靜態隨機種子

  • @@ 是佔位符目標的命令行,AFL 將用每個輸入文件名替換

 fuzzer將會對每個不同的輸入文件運行 $HOME/fuzzing_xpdf/install/bin/pdftotext <input-file-name> $HOME/fuzzing_xpdf/output 命令

136ca8997a56a258d67334180c7464bb.png

 出現錯誤,根據提示,執行以下操作:

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

 成功運行,等待一段時間後,發現已經有了一個crash

d19a6889f31d06cc4bcbe5c67fc4d940.png

 可以在$HOME/fuzzing_xpdf/out/ 目錄中找到這些崩潰文件。一旦發現第一次崩潰,就可以停止fuzzer,上圖中已經出現了一個獨特的崩潰。根據您的機器性能,最多可能需要一到兩個小時才能發生崩潰。

 爲了完成這個練習,下面嘗試使用指定的文件重現崩潰,調試崩潰發現問題,並且修復問題。

 重現崩潰

 在$HOME/fuzzing_xpdf/out/目錄下找到 crash 對應的文件。文件名類似於id:000000,sig:11,src:000390,time:103613,execs:71732,op:havoc,rep:16

68de27ea9a556cb90834a1a461ba960d.png

 將此文件作爲輸入傳遞給 pdftotext

$HOME/fuzzing_xpdf/install/bin/pdftotext '/home/fuzz/fuzzing_xpdf/out/default/crashes/<your_filename>' $HOME/fuzzing_xpdf/output

 它將導致段錯誤segmentation fault並導致程序崩潰。

df8ec55802dba13d344d4937133468b7.png

 調試

 使用 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,輸入run

gdb --args $HOME/fuzzing_xpdf/install/bin/pdftotext $HOME/fuzzing_xpdf/out/default/crashes/<your_filename> $HOME/fuzzing_xpdf/output

a62fa389bf7531bcc0465530ee5b3218.png

 然後輸入bt回溯查看棧幀

f7d3e69491621b282c5a0e6e14822d1f.png

 發現有許多次Parser::getObj的調用,它們似乎表示一個無限遞歸。如果你去 https://www.cvedetails.com/cve/cve-2019-13288/ ,你可以看到描述符合我們從 GDB 得到的回溯。

 實驗推薦

 實驗:Fuzz之AFL(合天網安實驗室) 點擊進入實操>>

 更多靶場實驗練習、網安學習資料,請點擊這裏>>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章