如何对二进制代码进行定向模糊测试以扫描用后释放漏洞
写在前面的话
定向灰盒模糊测试(DGF)类似AFLGo,旨在对预先选择的潜在易受攻击的目标位置执行压力测试,应用于不同的安全场景:(1)漏洞复现;(2)补丁测试;(3)静态分析报告验证;近期,研究人员也做了很多工作,有效地提高了定向模糊测试的有效性和效率。
为此,我们开发出了UAFuzz,它是一个在二进制代码级别上专门针对用后释放漏洞(UAF)的定向模糊测试工具。该工具可以通过仔细调整定向模糊测试的关键组件来满足这个类型漏洞的特定特性。在释放堆元素之后,如果再次使用堆元素时便会触发用后释放漏洞。大家都知道,检测UAF漏洞是比较困难且复杂的,因为PoC输入需要在同一内存位置触发三个事件序列(分配、释放和使用),这里涉及到目标程序的多个功能。
总体而言,UAFuzz的工作流与定向模糊测试工具相似,并且对模糊测试过程的相关数据进行了高亮处理,以橙色高亮显示。该工具能够对所有与内存相关的UAF事件进行完整的堆栈跟踪。与现有的可独立选择目标的一般定向方法不同,我们考虑了目标之间的关系来提高方向性。首先,UAFuzz的静态预计算在二进制级别上很快。其次,我们引入了新的排序感知输入指标,以引导模糊测试器在运行时朝着正确的方向走下去。最后,我们只对覆盖预期跟踪中所有目标的潜在输入进行分类,并对不太可能触发漏洞的输入进行预过滤。
工具安装
首先,我们需要在本地主机上安装好IDA Pro v6.9(32位)和Python v2.7,之后我们还会添加针对更多开源代码反汇编工具的支持,比如说Radare等等。
除此之外,我们还需要使用Graph-Easy v0.7.6来转换IDA的调用图。
在本地主机安装Valgrind分析工具、二进制源码分析框架BINSEC和基于覆盖引导的灰盒模糊测试工具AFL v2.52b。
我们的工具测试环境为Ubuntu 16.04(64位),安装配置代码如下:
# Install Ocaml and prerequisite packages for BINSEC via OPAM sudo apt update sudo apt install ocaml ocaml-native-compilers camlp4-extra opam opam init opam switch 4.05.0 opam install merlin ocp-indent caml-mode tuareg menhir ocamlgraph ocamlfind piqi zmq.5.0.0 zarith llvm.6.0.0 # Install Python's packages sudo pip install networkx pydot # Checkout source code git clone https://github.com/strongcourage/uafuzz.git # Environment variables export IDA_PATH = /path/to/ida-6.9/idaq export GRAPH_EASY_PATH=/path/to/graph-easy cd uafuzz; export UAFUZZ_PATH=`pwd` # Compile source code ./scripts/build.sh uafuzz # Help for IDA/UAFuzz interface ./binsec/src/binsec -ida-help ./binsec/src/binsec -uafuzz-help
代码结构
我们的模糊测试工具基于QEMU模式的AFL v2.52b实现,以实现针对轻量级静态分析的模糊测试。我们当前使用IDA Pro v6.9来提取目标代码的控制流图以及调用图。
uafuzz ├── binsec/src │ └── ida: a plugin to import and process IDA's CFGs and call graph │ └── uafuzz: fuzzing code │ │ └── afl-2.52b: core fuzzing built on top of AFL-QEMU │ │ └── uafuzz_*.ml(i): a plugin to compute static information and communicate with AFL-QEMU └── scripts: some scripts for building and bug triaging
应用场景一:漏洞复现
我们先用一个简单的UAF漏洞举个例子。针对这个漏洞,无论是AFL-QEMU,甚至是带有源代码级目标的定向模糊测试工具AFLGo都无法在6小时内检测到它,而UAFuzz可以在Valgrind的帮助下在几分钟内检测到它。
# Run AFL-QEMU $UAFUZZ_PATH/tests/example.sh aflqemu 360 # Run AFLGo given targets at source-level $UAFUZZ_PATH/tests/example.sh aflgo 360 # Run UAFuzz $UAFUZZ_PATH/tests/example.sh uafuzz 360 $UAFUZZ_PATH/tests/example/example.valgrind
对于真实场景,我们还需要使用UAF模糊化基准进行评估。
# Checkout the benchmark git clone https://github.com/strongcourage/uafbench.git cd uafbench; export UAFBENCH_PATH=`pwd`
Valgrind获得的这个UAF 漏洞的堆栈跟踪如下:
// stack trace for the bad Use ==5358== Invalid read of size 1 ==5358== at 0x40A9393: vfprintf (vfprintf.c:1632) ==5358== by 0x40A9680: buffered_vfprintf (vfprintf.c:2320) ==5358== by 0x40A72E0: vfprintf (vfprintf.c:1293) [6] ==5358== by 0x80AB881: error (elfcomm.c:43) [5] ==5358== by 0x8086217: process_archive (readelf.c:19409) [1] ==5358== by 0x80868EA: process_file (readelf.c:19588) [0] ==5358== by 0x8086B01: main (readelf.c:19664) // stack trace for the Free ==5358== Address 0x4221dc0 is 0 bytes inside a block of size 80 free'd ==5358== at 0x402D358: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) [4] ==5358== by 0x8086647: process_archive (readelf.c:19524) [1] ==5358== by 0x80868EA: process_file (readelf.c:19588) [0] ==5358== by 0x8086B01: main (readelf.c:19664) // stack trace for the Alloc ==5358== Block was alloc'd at ==5358== at 0x402C17C: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) [3] ==5358== by 0x80AD97E: make_qualified_name (elfcomm.c:906) [2] ==5358== by 0x8086350: process_archive (readelf.c:19435) [1] ==5358== by 0x80868EA: process_file (readelf.c:19588) [0] ==5358== by 0x8086B01: main (readelf.c:19664)
应用场景二:补丁测试
我们使用GNU补丁的CVE-2018-6952来说明产生不同漏洞触发输入以支持漏洞修复过程的重要性。这个GNU补丁中存在一个双重释放漏洞,不过开发人员已经在9c98635中修复了该漏洞。但是,通过使用CVE-2018-6952的堆栈跟踪,UAFuzz发现了最新版本2.7.6(commit 76e7758)中仍然存在问题。总的来说,我们使用现有缺陷的PoC输入和模糊语料库中的有效文件作为高质量的种子。
# Fuzz patched version of CVE-2018-6952 $UAFBENCH_PATH/CVE-2019-20633.sh uafuzz 360 $UAFBENCH_PATH/valgrind/CVE-2018-6952.valgrind
应用场景三:静态分析报告验证
一种可能的混合方法是将UAFuzz与GUEB相结合,GUEB是唯一使用Ocaml并针对UAF漏洞编写的二进制级静态分析器。然而,GUEB会产生许多误报,并且目前无法正确处理复杂的二进制文件。因此,我们目前对GUEB进行改进,并将其整合到BINSEC中,然后使用GUEB报告中提取的目标来指导UAFuzz。
项目地址
UAFuzz:【GitHub传送门】
如何使用Bulwark实现组织的资产以及漏洞管理
概述
Bulwark是一款针对企业和组织机构的组织资产和漏洞管理工具,该工具继承了Jira,旨在帮助企业安全从业人员生成关于组织内部的应用程序安全报告。
需要注意的是,该项目目前还处于前期开发阶段,因此可能会存在运行不稳定的情况。
工具下载
git clone https://github.com/softrams/bulwark.git
使用Docker启动
首先,我们需要在本地环境中安装好Docker【下载地址】。
接下来,创建一个.env文件,并提供下列参数配置:
MYSQL_DATABASE="bulwark" MYSQL_PASSWORD="bulwark" MYSQL_ROOT_PASSWORD="bulwark" MYSQL_USER="root" MYSQL_DB_CHECK="mysql" DB_PASSWORD="bulwark" DB_URL="172.16.16.3" DB_ROOT="root" DB_USERNAME="bulwark" DB_PORT=3306 DB_NAME="bulwark" DB_TYPE="mysql" NODE_ENV="production" DEV_URL="http://localhost:4200" PROD_URL="http://localhost:5000" JWT_KEY="changeme" JWT_REFRESH_KEY="changeme" CRYPTO_SECRET="changeme" CRYPTO_SALT="changeme"
构建并启动Bulwark容器:
docker-compose up
开启/停止Bulwark容器:
docker-compose start docker-compose stop
移除Bulwark容器:
docker-compose down
此时,我们可以访问localhost:5000来使用Bulwark。
本地安装
$ git clone https://github.com/softrams/bulwark.git $ cd bulwark $ npm install
以开发模式运行:
$ npm run start:dev
以生产模式运行:
$ npm start
环境变量
在项目根目录中创建一个.env文件,应用程序将使用dotenv来解析这个文件。
DB_PASSWORD
DB_PASSWORD="somePassword"
这个变量用于设置数据库密码。
DB_USERNAME
DB_USERNAME="foobar"
这个变量用于设置数据库用户名。
DB_URL
DB_URL=something-foo-bar.dbnet
这个变量用于设置数据库URL地址。
DB_PORT
DB_PORT=3306
这个变量用于设置数据库端口号。
DB_NAME
DB_NAME="foobar"
这个变量用于设置数据库名称。
DB_TYPE
DB_TYPE="mysql"
这个应用程序使用的是MySQL来作为数据库。
NODE_ENV
NODE_ENV=production
这个变量用于设置节点环境。
DEV_URL="http://localhost:4200"
如果需要使用不同端口,可配置该参数。
PROD_URL="http://localhost:5000"
如果需要使用不同端口,可配置该参数。
JWT_KEY
JWT_KEY="changeMe"
这个变量用于设置JWT凭证。
JWT_REFRESH_KEY
JWT_REFRESH_KEY="changeMe"
这个变量用于刷新JWT凭证。
CRYPTO_SECRET
CRYPTO_SECRET="randomValue"
这个变量用于设置Scrypt密码。
CRYPTO_SALT
CRYPTO_SECRET="randomValue"
这个变量用于设置Scrypt盐值。
空.env文件模板
DB_PASSWORD="" DB_URL="" DB_USERNAME="" DB_PORT=3306 DB_NAME="" DB_TYPE="" NODE_ENV="" DEV_URL="http://localhost:4200" PROD_URL="http://localhost:5000" JWT_KEY="" JWT_REFRESH_KEY="" CRYPTO_SECRET="" CRYPTO_SALT=""
创建初始数据库迁移
首先,我们需要使用下列命令来创建初始数据库迁移:
$ npm run migration:init
接下来,运行初始数据库迁移:
$ npm run migration:run
默认凭证
我们需要在初始安装过程中创建一个用户账号,凭证如下:
电子邮箱:admin@example.com 密码:changeMe
首次登录时,别忘了在账号配置中更新默认的用户密码。
Bulwark基于下列项目开发实现
许可证协议
本项目的开发与发布遵循MIT开源许可证协议。
项目地址
Bulwark:【GitHub传送门】
扫描关注公众号