使用AFL挖掘libxml2
字数 1211 2025-08-24 16:48:16
AFL挖掘libxml2漏洞实战指南
前言
XML(可扩展标记语言)是一种用于传输和存储数据的标记语言,与HTML专注于数据显示不同,XML专注于数据内容。libxml2是一个用于处理XML格式文件的C语言库和工具包。本指南将详细介绍如何使用AFL(American Fuzzy Lop)模糊测试工具来挖掘libxml2中的漏洞。
环境准备
安装必要工具
sudo apt install autoconf
sudo apt install libtool-bin
获取AFL并编译
- 下载AFL并编译
afl-clang-fast(需要已安装clang) - 切换到AFL的
llvm_mode目录执行make - 返回AFL根目录执行
make install
编译libxml2-2.9.2
cd libxml2根目录
./autogen.sh --prefix=/path/to/install --with-python-install-dir=/path/to/install CC=afl-clang-fast
AFL_USE_ASAN=1 make -j 4
sudo make -j 4 install
参数说明:
--prefix:指定安装目录--with-python-install-dir:指定Python安装目录AFL_USE_ASAN=1:启用ASAN(AddressSanitizer)内存错误检测器-j 4:使用4个进程并行编译
编写测试程序(harness.c)
基础版本
#include "libxml/parser.h"
#include "libxml/tree.h"
int main(int argc, char **argv) {
if (argc != 2) return 1;
xmlInitParser();
while (__AFL_LOOP(1000)) {
xmlDocPtr doc = xmlReadFile(argv[1], NULL, 0);
if (doc != NULL) xmlFreeDoc(doc);
}
xmlCleanupParser();
return 0;
}
增强版本(提高覆盖率)
#include <stdio.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
static void print_element_names(xmlNode *a_node) {
xmlNode *cur_node = NULL;
for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
printf("node name: %s\n", cur_node->name);
}
print_element_names(cur_node->children);
}
}
int main(int argc, char **argv) {
xmlDoc *doc = NULL;
xmlNode *root_element = NULL;
if (argc != 2) return 1;
doc = xmlReadFile(argv[1], NULL, 0);
if (doc == NULL) {
printf("error: could not parse file %s\n", argv[1]);
xmlFreeDoc(doc);
xmlCleanupParser();
return -1;
}
while (__AFL_LOOP(1000)) {
root_element = xmlDocGetRootElement(doc);
print_element_names(root_element);
}
xmlFreeDoc(doc);
xmlCleanupParser();
return 0;
}
编译测试程序
动态链接方式(适合普通测试)
AFL_USE_ASAN=1 afl-clang-fast ./harness.c -I ./build/include/libxml2/ -L ./build/lib -lxml2 -lz -lm -g -o harness
静态链接方式(适合AFL模糊测试)
AFL_USE_ASAN=1 afl-clang-fast ./harness.c -I ./build/include/libxml2/ ./build/lib/libxml2.a -lz -lm -g -o harness
参数说明:
-I:指定头文件目录-lz:使用zlib库-lm:使用math库-g:包含调试信息
启动AFL模糊测试
afl-fuzz -m none -i in -o out -x ~/afl-2.52b/dictionaries/xml.dict ./harness @@
参数说明:
-m none:不限制内存使用(便于ASAN检测)-i in:输入样本目录-o out:输出目录-x:指定XML字典文件@@:表示输入文件参数
样本准备与优化
- 获取样本:从MozillaSecurity/fuzzdata获取XML样本
- 筛选小样本:
find ./xml/ -size -1024c > tmp.txt mkdir less1k for l in `cat ./tmp.txt`; do cp $l ./less1k/; done; - 精简样本:
afl-cmin -i less1k/ -o cmin-out/ -m none ./harness1 @@ - 最小化样本:
mkdir tmin-out cd cmin-out for i in *; do afl-tmin -i $i -o ../tmin-out/$i -m none -- ../harness @@; done;
漏洞分析
常见漏洞类型
- 堆溢出读:在解析特定格式XML时可能导致一个字节的堆溢出读
- 下标越界:在
xmlDictQLookup函数中,未充分检查len - (plen + 1 + 1)可能导致下标越界(CVE-2015-7497)
漏洞修复
- 误报修复:修改
parse.c,用自定义函数替换宏定义,并添加__attribute__((no_sanitize_address))标记 - CVE-2015-7497修复:根据官方补丁修改
dict.c,增加长度检查
改进模糊测试效果
- 增加测试函数:在harness中添加更多libxml2函数调用
- 使用更全面的字典:替换AFL自带的XML字典,使用更全面的libxml_xml_read_memory_fuzzer.dict
- 使用screen保持会话:
screen afl-fuzz -m none -i ./tmin-out/ -o out2 -x ./libxml_xml_read_memory_fuzzer.dict -- ./harness @@
参考资料
通过本指南,您可以系统地学习如何使用AFL挖掘libxml2中的漏洞,包括环境搭建、测试程序编写、样本优化和漏洞分析等关键步骤。