
视频:https://youtu.be/EYBB4BHsp9E
./outputmalicious.tar 归档,其中包含一些走私内容的示例,注释逐步骤和逐块解释了正在进行的操作使用提供的 reproduce 脚本 或手动操作
运行 malicious-payload 生成载荷 malicious.tar
将此文件传递给我们的 vulnerable-extract 应用会产生:
/vulnerable-extract$ ll output/
total 12
drwxrwxr-x 2 airinei airinei 4096 Jan 19 22:40 ./
drwxrwxr-x 5 airinei airinei 4096 Jan 19 22:40 ../
-rw-rw-r-- 1 airinei airinei 0 Jan 1 1970 benign_file.txt
-rw-rw-r-- 1 airinei airinei 18 Jan 1 1970 sh_profile_hijack
而运行我们操作系统自带的 tar(本例中为 (GNU tar) 1.35)工具则会输出:
malicious-payload$ tar -tvf malicious.tar
---------- 0/0 1024 1970-01-01 02:00 benign_file.txt
注意,它看到文件大小为 1024
或者使用 astral-tokio-tar 0.5.6(而非已废弃的 tokio-tar 0.3.1)可以正确解压该归档。
CVE-2025-62518(TARmageddon)是 tokio-tar Rust 库中的一个安全漏洞(Rust 漏洞 😮)。这是一个逻辑错误,涉及 tar 格式头部解析方式,允许攻击者走私文件。
该缺陷存在于处理 PAX 扩展头部的逻辑中。在 TAR 归档中,有以下不同的头部类型:
USTAR:包含文件名、权限和大小的标准头部。PAX(类型 x):用于提供元数据(如非常大的文件大小)的扩展头部,应用于归档中下一个文件。当存在 PAX 头部时,解析器必须通过优先使用 PAX 元数据而非标准 USTAR 头部来解析文件的实际大小。
但为什么会有 2 种头部类型,并且对于看起来相同的内容存在优先级?因为 TAR 格式很古老(标准化于 1988 年),而 USTAR 有其局限性(大小最大 8GB,文件名最多 256 个字符)。这是一个问题,因此 PAX 头部于 2001 年加入,以支持更大的文件和更长的文件名。
在易受攻击的 tokio-tar 版本中,解析器正确地从 PAX 头部获取文件内容读取器的大小,但错误地使用 USTAR 头部的大小来确定下一个文件头部从哪里开始。
问题的核心是 指针不匹配。当易受攻击的库处理文件时,它使用两个不同的内部“头”来读取流:
在正常归档中,这两个头是一致的。但在 TARmageddon 中,我们强制它们不一致。通过将 PAX 大小设置为 1024,USTAR 大小设置为 0,我们制造了一个悖论:
benign_file.txt。0,认为 “我已经在文件末尾了。” 它停留在当前位置。因此,解析器头 将 1024 字节块内的数据视为下一组指令。如果那些数据看起来像一个有效的 TAR 头部,该库将“发现”并提取一个第二个文件,而该文件在归档的全局结构中实际上并不存在。
走私载荷:
载荷被精心构造为一系列 512 字节块。以下是 malicious-payload 生成器中使用的布局:
| 块 | 角色 | 描述 |
|---|---|---|
| 1 & 2 | PAX 元数据 | 声明下一个文件长度为 1024 字节。 |
| 3 | 基本头部 | benign.txt。关键是将大小设为 0。 |
| 4 | 走私头部 | backdoor.sh。隐藏在“数据”区域内。 |
| 5 | 走私数据 | 恶意内容(例如 shell 别名)。 |
| 6 & 7 | 结束标志 | 标准的空块终止。 |
由于标准工具(如 GNU tar)正确遵循 PAX 大小,它们将块 4 和 5视为属于 benign_file.txt 的无害二进制数据。它们永远不会“执行”块 4 中的头部。
这个 crate 存在漏洞如何被利用?文件被走私到归档中为何重要?
攻击者将恶意文件走私到构建系统中。无论是在开发环境还是 CI 机器上解压,都可能覆盖合法的构建文件,从而危害该机器,甚至诱骗构建系统签署恶意文件。
扫描器检查 .tar 文件时,仅以正确模式扫描,而解压时可能出现的非期望文件并未被扫描。
灵感来源于这篇文章