软件安全 @ 洛桑联邦理工学院(EPFL),2025 年春季
在本实验中,我们在 Google 的 OSS-Fuzz 基础设施中增强了对 tmux 终端复用器的模糊测试工作。我们首先通过评估现有 input-fuzzer 测试工具的行覆盖率建立了基线(分别在提供和不提供其种子语料库的情况下运行),并注意到两者的初始覆盖率相当。随后,我们识别出 tmux 中两个未被基线模糊测试器充分覆盖的重要代码区域。为了弥补这些覆盖缺口,我们开发并评估了两个新的针对性模糊测试工具 cmd-fuzzer 和 argument-fuzzer,证明了它们能够改善这些先前测试不足区域的覆盖率。由于这些模糊测试改进未能在项目时间范围内发现新的严重漏洞,我们的崩溃分析聚焦于一个已知的历史漏洞。我们为 CVE-2020-27347(一个基于栈的缓冲区溢出)开发了概念验证(PoC),分析了其根本原因,讨论了已实施的修复方案,并评估了其安全影响。
本项目旨在利用 OSS-Fuzz 框架,在开源终端复用器 tmux 上应用并增强模糊测试技术。项目涵盖以下几个关键阶段:
基线评估(第 1 部分):
tmux 现有的 input-fuzzer 测试工具。覆盖缺口分析(第 2 部分):
tmux 中未被 input-fuzzer 充分覆盖的重要代码区域。arguments.c)以及命令解析/执行逻辑(cmd-parse.c、cmd-*.c 模块),将其作为改进的关键领域。模糊测试器改进(第 3 部分):
argument-fuzzer:专门用于测试 arguments.c 中的命令行参数解析逻辑。cmd-fuzzer:用于测试命令解析和执行路径,针对 cmd-parse.c 及各种 cmd-*.c 模块。崩溃分析(第 4 部分):
tmux 中一个已知的、先前存在的漏洞(CVE-2020-27347)进行深入分析。最终提交按如下方式组织(位于 submission/ 目录内):
submission/
├── README.md # This file
├── part_1/ # Files for Part 1: Baseline Evaluation
│ ├── oss-fuzz.diff # Diff for removing seed corpus for input-fuzzer
│ ├── project.diff # (Likely empty or minor for Part 1)
│ ├── remove_seed_corpus.patch # The actual patch file used
│ ├── report/ # HTML Coverage reports for input-fuzzer
│ │ ├── w_corpus/
│ │ └── wo_corpus/
│ ├── run.w_corpus.sh # Script to run input-fuzzer with corpus
│ └── run.wo_corpus.sh # Script to run input-fuzzer without corpus
├── part_3/ # Files for Part 3: Fuzzer Improvements
│ ├── coverage_noimprove/ # Baseline coverage (e.g., from input-fuzzer without corpus)
│ │ └── ...
│ ├── improve1/ # Improvement 1: argument-fuzzer
│ │ ├── coverage_improve1/ # Coverage report for argument-fuzzer
│ │ ├── oss-fuzz.diff # OSS-Fuzz config changes for argument-fuzzer
│ │ ├── project.diff # Tmux changes for argument-fuzzer (e.g., new .cc, Makefile.am)
│ │ └── run.improve1.sh # Script to run argument-fuzzer
│ └── improve2/ # Improvement 2: cmd-fuzzer
│ ├── coverage_improve2/ # Coverage report for cmd-fuzzer
│ ├── oss-fuzz.diff # OSS-Fuzz config changes for cmd-fuzzer
│ ├── project.diff # Tmux changes for cmd-fuzzer
│ └── run.improve2.sh # Script to run cmd-fuzzer
├── part_4/ # Files for Part 4: Crash Analysis (CVE-2020-27347)
│ ├── environment/ # Docker environment for PoC
│ │ ├── Dockerfile
│ │ ├── run_tmux_cve_test.sh # Core PoC test logic
│ │ ├── test_fixed.sh
│ │ └── test_vulnerable.sh
│ └── run.poc.sh # Script to build Docker image and run PoC tests
└── report.pdf # The comprehensive project report
(注:包含 _run_fuzz_core.sh 的 scripts/ 目录是一个辅助工具目录;如果此 README 位于真正的项目根目录(与 submission/ 同级)中,则该目录应属于根目录的一部分。)
所有模糊测试活动以及 CVE PoC 复现均设计为在由 shell 脚本编排的 Docker 环境中运行。
所有模糊测试活动以及 CVE PoC 复现均设计为在由 shell 脚本编排的 Docker 环境中运行。
前提条件:
bash shell 和 git 客户端。oss-fuzz,则需为 [email protected] 配置 SSH 密钥(若在项目根目录中未找到 oss-fuzz/,脚本会尝试克隆)。或者,你可以预先将 https://github.com/google/oss-fuzz.git 克隆到项目根目录。通用脚本架构:
本项目使用一个集中的核心脚本 scripts/_run_fuzz_core.sh(不包含在 submission/ 目录中,但属于本 README 所假设的整体项目结构的一部分)。位于 submission/part_1/、submission/part_3/improve1/、submission/part_3/improve2/ 和 submission/part_4/ 中的各个运行脚本负责:
oss-fuzz 仓库的全新检出应用特定运行场景的 oss-fuzz.diff 补丁来设置特定的测试环境(相对于大多数运行脚本,该仓库应位于 ../../oss-fuzz)。PROJECT、HARNESS、LABEL、项目特定补丁的路径以及输出目录)。_run_fuzz_core.sh 脚本,该脚本随后负责:
tmux 添加新的模糊测试器源文件)。submission/ 目录结构中指定的位置。运行脚本:
通常建议从项目的根目录执行运行脚本,以确保 oss-fuzz/ 和输出目录的相对路径解析正确。
1. 第 1 部分:基线评估(input-fuzzer)
这些脚本评估 tmux 现有的 input-fuzzer。
# From the project root directory:
./submission/part_1/run.w_corpus.sh # Run input-fuzzer with default seed corpus
./submission/part_1/run.wo_corpus.sh # Run input-fuzzer without seed corpus
run.w_corpus.sh 使用 tmux 关于种子语料库的默认构建行为。
run.wo_corpus.sh 将 submission/part_1/remove_seed_corpus.patch(通过其本地的 oss-fuzz.diff,该 diff 会调用此补丁或整合其更改)应用到 oss-fuzz/projects/tmux/build.sh,以确保不使用初始种子语料库。覆盖率报告将分别导出到 submission/part_1/report/w_corpus/ and submission/part_1/report/wo_corpus/ 和 submission/part_1/report/wo_corpus/。
2. 第 3 部分:模糊测试器改进(input-fuzzer)
改进 1(argument-fuzzer):针对 arguments.c。
# From the project root directory:
./submission/part_3/improve1/run.improve1.sh
改进 2(cmd-fuzzer):针对 cmd-parse.c 和命令执行。
# From the project root directory:
./submission/part_3/improve2/run.improve2.sh
每个 run.improveX.sh 脚本都会应用其本地的 oss-fuzz.diff,并将 PROJECT_PATCH_FILE 设置为其本地的 project.diff(该补丁会向 tmux 添加新的模糊测试器代码并更新 Makefile.am)。覆盖率报告将导出到相应的 submission/part_3/improveX/coverage_improveX/ 目录。submission/part_3/coverage_noimprove/ 目录包含第 1 部分的基线覆盖率,以供比较。
# From the project root directory:
./submission/part_4/run.poc.sh
该脚本构建一个专用的 Docker 镜像(基于 submission/part_4/environment/Dockerfile),并针对已修补的提交 a868bac 测试 tmux 3.1b(易受攻击版本)。
(详细的解释、图表和表格可在完整的 report.pdf 中找到)
input-fuzzer 的影响很小。tmux 的大部分代码区域(尤其是参数解析(arguments.c)、命令解析/执行(cmd-parse.c、cmd-*.c)以及客户端/服务器逻辑(client.c、server.c))基本未被覆盖(例如,arguments.c 的行覆盖率约为 5.8%)。argument-fuzzer(针对 arguments.c): 使 arguments.c 的行覆盖率达到 66.62%,相比约 5.8% 的基线有了大幅提升。cmd-fuzzer(针对命令解析与执行): 将 cmd-parse.c 的行覆盖率从约 27% 提高到 42.58%,函数覆盖率提高到 77.78%。arguments.c 的覆盖率也上升到了 45.54%。cmd.c 的行覆盖率达到 39.14%。cmd-*.c 模块(例如 cmd-bind-key.c、cmd-set-options.c 的函数覆盖率达到 50%)以及按键处理例程(key-string.c 的行覆盖率达到 30%,key-bindings.c 的行覆盖率达到 6.05%)中实现了新的或显著提升的覆盖率。\033[::::::7::1:2:3::5:6:7:m 在 tmux 3.1b(提交 6a33a12)上成功复现了 CVE-2020-27347(SGR 转义序列解析中的栈缓冲区溢出)。a868bac(包含该修复并对应版本 3.1c)不会受到该崩溃的影响。argument-fuzzer、cmd-fuzzer)需要对 tmux 内部的参数和命令处理逻辑有良好的理解,以便针对特定的未覆盖代码路径。cmd-fuzzer,以覆盖更广泛的 cmd-*.c 模块,尤其是那些涉及复杂状态交互(如窗口、布局或窗格操作)的模块。cmd-parse.y 中的语法定义来生成语法上更有效且更复杂的命令序列。