

本仓库演示了 tokio-tar 及相关异步 Rust tar 库中的一个严重错误:在计算下一个文件头位置之前,未应用 PAX 扩展头中的 size 覆盖值。
根本原因: 处理包含 PAX 扩展头(且扩展头覆盖了文件大小)的 tar 文件时,库使用八进制的大小字段(通常为零)进行位置计算,而非 PAX 覆盖值。
影响: 这会导致解析器跳入文件内容,并将其误认为 tar 文件头,从而提取错误的文件。
已知受影响的库:
async-tar https://github.com/dignifiedquire/async-tartokio-tar https://github.com/vorot93/tokio-tarkrata-tokio-tar https://github.com/edera-dev/tokio-tarastral-tokio-tar https://github.com/astral-sh/tokio-tar# 依赖:CMake、Rust/Cargo、C++ 编译器、系统 tar 命令
cmake -S . -B build
cmake --build build --target generate_report
这将:
build/output/ 中生成详细报告├── disclosure/ # 安全披露文档树
│ └── blast_radius/ # 依赖 tokio-tar 变体的项目记录
├── repro_generator/ # C++ 工具,用于生成再现错误的 tar 文件
├── tar-bug-detector/ # Rust 工具,比较各 tar 库的行为
├── tarwalk/ # 正确的 C++ tar 解析器
│ ├── tarwalk.cpp # 正确处理 PAX
│ └── tarwalk_bad.cpp # 复现相同错误
├── CMakeLists.txt # 构建系统
├── generate_report.cmake # 报告生成
└── README.md # 本文件
Header -> Content (size from octal field) -> Next Header
PAX Header (size=1024) -> File Header (octal size=0) -> Content (1024 bytes) -> Next Header
PAX Header (size=1024) -> File Header (octal size=0) -> Content (0 bytes) -> WRONG POSITION
↓
Reading content as headers!
Docker save 创建的 tar 文件包含:
etc/、usr/)开头pax_bug_compact.tar - 最小化再现案例正确库(GNU tar、同步 tar crate):
normal.txt -> blob.bin -> marker.txt
有错误的库(tokio-tar):
normal.txt -> blob.bin -> INNER_FILE -> marker.txt
出现 INNER_FILE 即表明存在错误 —— 库跳入 blob.bin 内容中,将伪 tar 头误认为真实条目。
修复方法是在位置计算之前应用 PAX 覆盖值:
// 读取文件头
let mut file_size = header.size();
// 在计算下一个位置之前,应用 PAX 覆盖值
if let Some(pax_size) = pending_pax.get("size") {
file_size = pax_size.parse().unwrap();
}
// 现在使用有效大小计算下一个文件头的位置
let next_pos = current_pos + 512 + pad_to_512(file_size);
本再现代码仅供安全研究和负责任披露使用。
原始源代码许可证见 COPYING 文件。