【免费下载链接】strata
The best file manager on Linux
Strata是 Linux 上体验最好的文件管理器之一,也是 Rust 编写的 GTK 应用。本文深入介绍 Strata 压缩包解压安全机制:它如何防御经典的Zip Slip 路径穿越漏洞、如何拒绝符号链接遍历,以及项目如何通过编译期 lint 近乎彻底地禁止 unsafe Rust 代码。
先看 Strata 的列视图界面,解压动作就藏在你每天使用的右键菜单里:
什么是 Zip Slip:压缩包里藏着的"越狱"路径
🕵️ 压缩包(ZIP / 7Z / RAR / TAR)里每个文件的"名字"本质上是不可信的用户输入。攻击者可以手工构造一条名为../../etc/cron.d/backdoor的成员路径:
- 若解压程序把"目标文件夹 + 成员路径"直接拼接,
../会一路把文件写到你选择的目录之外; - 这就是臭名昭著的Zip Slip漏洞,曾让无数主流解压工具"中枪"。
Strata 的官方设计文档对此有明确定义:
如果解压器把选中文件夹与
../report.txt原样拼接,文件系统会把结果解析到该文件夹旁边而不是里面。
完整说明见 docs/archives.md。
第一道防线:成员路径净化,../被强制钳制在解压目录内
核心函数是 sanitized_archive_path,它对每个成员路径逐段处理,规则非常克制:
| 输入形态 | 处理结果 |
|---|---|
../report.txt | 净化为report.txt(留在目录内) |
folder/../report.txt | 净化为report.txt |
/tmp/marker、\\server\share | ❌ 直接拒绝(绝对路径 / UNC 路径) |
C:\tmp\marker、C:marker | ❌ 直接拒绝(Windows 盘符前缀) |
| 空路径 | ❌ 直接拒绝 |
几个值得注意的细节:
- 🔒单个越界成员不会毁掉整个解压:路径被"钳制"后解压继续处理后续成员,而不是整体中止;
- ⚔️反斜杠一并拦截:
safe\..\..\marker中的\会先被归一化为/,Windows 风格的穿越同样无处遁形; - 📛冲突自动改名:两条成员净化后都叫
report.txt时,会生成report.txt和report (2).txt,绝不互相覆盖。
对应的单元测试把攻击向量写得明明白白:/tmp/marker、C:\tmp\marker、//server/share/marker全部必须被拒绝,见 destination/tests.rs#L21-L55。
第二道防线:固定目录描述符 + NOFOLLOW,文件系统层面拒绝符号链接
光净化字符串还不够——攻击者还可以在解压进行到一半时,把目录树里的某个节点偷偷换成符号链接,诱导写入被重定向。Strata 在 ExtractionDestination 里用操作系统机制堵死了这条路:
- 📌固定根目录(pinned fd):解压目标通过
openat2打开后,后续所有操作都以这个文件描述符为基准(descriptor-relative),即使路径中途被替换也无法劫持写入; - 🚫逐级
O_NOFOLLOW下降:每一级子目录都以DIRECTORY | NOFOLLOW打开(见 descend),符号链接根本无法被"当作目录"穿越; - 🎭隐藏 staging 目录:文件先写入
.strata-extraction-<id>暂存目录,解压全部完成后才一次性发布。密码错误时暂存内容被整体丢弃,失败/取消时残留文件则保留在归档同名文件夹中,方便排查; - ⚡no-replace 原子发布:最终发布使用"绝不覆盖"的目录重命名,目标已存在时自动改成
photos (1)/、photos (2)/,永远不会替换你的既有文件; - 🔐权限位过滤:每个成员恢复存储的权限位时,setuid / setgid / sticky 位被强制剥离,再叠加 umask;FIFO 和设备节点直接拒绝创建。
解压入口本身也做了校验
🖱️ 只有"常规文件(或指向常规文件的符号链接)+ 本地路径 + 已识别的压缩包扩展名"才会提供Extract here/Extract to…菜单项。命名为photos.zip的文件夹、FIFO、socket、断链统统不算数。即使你打开菜单后文件被外部修改,操作层还会在执行前二次校验路径——这就是图中右键菜单的行为来源:
另外,只有解码器明确报告"密码缺失或错误"才会弹出密码框;错误文案永远不参与判断,所以压缩包成员名里包含 "password" 字样也骗不出密码输入框。
unsafe 代码策略:Rust 的"默认拒绝"如何落地
🛡️ 解压安全还建立在底层语言之上:Strata 是一个safe-Rust 代码库,unsafe是例外而非常规工具。完整策略写在 docs/unsafe-code.md,而强制手段来自 Cargo.toml 的 lint 配置:
| Lint 规则 | 效果 |
|---|---|
unsafe_code = "deny" | 全局禁止 unsafe 代码 |
unsafe_op_in_unsafe_fn = "deny" | 禁止在 unsafe 函数里藏 unsafe 操作 |
multiple_unsafe_ops_per_block = "deny" | 每个 unsafe 块只允许一个unsafe 操作 |
undocumented_unsafe_blocks = "deny" | 每个 unsafe 块必须写SAFETY:注释 |
missing_safety_doc = "deny" | 公开 unsafe 函数必须有安全文档 |
禁止#[allow(...)] | 只能用带 reason 的#[expect(...)],删掉操作后编译器会立刻报"过期的例外" |
CI 用 Clippy 运行且warning 即 error,任何违规都会直接阻断合并。
目前整个仓库只有两处经过批准的例外:
- 📄字体注册(src/assets.rs):fontconfig 的 C API 没有合适的 safe 封装,仅在单线程启动期使用 3 个 FFI 调用;
- 🧱浏览器沙箱 fork 边界(src/sandbox/browser/):
fork+ namespace 隔离没有 safe API,用于把媒体解码器关进一次性进程沙箱——这本身也是预览安全的一部分。
小结:三层纵深防御如何协同
✅ Strata 的压缩包解压安全不靠单点,而是层层设防:
- 路径净化层——成员路径逐段解析,
..钳制在解压根内,绝对路径与盘符前缀直接拒绝; - 文件系统层——固定描述符 + NOFOLLOW 下降 + staging 目录 + no-replace 发布 + 权限位剥离,符号链接与中途替换攻击全部失效;
- 语言与流程层——safe-Rust + 编译期 lint 封死 unsafe 后门,解压目标二次校验、密码弹窗只信解码器结果。
对普通用户而言,这意味着:无论打开来路多么可疑的压缩包,解压产物都只可能落在你选的文件夹里——这正是"最好的文件管理器"应该给出的安全感。
【免费下载链接】strata
The best file manager on Linux
相关推荐
Aholo Viewer:重新定义3D高斯光栅化!高性能3DGS渲染引擎全面解析
Aholo Viewer:重新定义3D高斯光栅化!高性能3DGS渲染引擎全面解析 Aholo Viewer 是一款高性能的3D高斯光栅化(3DGS)渲染引擎,专
如何快速掌握Node.js ZIP处理:adm-zip完整实战指南
如何快速掌握Node.js ZIP处理:adm zip完整实战指南 adm zip是一个强大的Node.js ZIP压缩解压库,让开发者能够轻松创建、读取和修改
开发工具如何使用radare2进行代码解压缩与重建:完整指南
如何使用radare2进行代码解压缩与重建:完整指南 radare2是一款功能强大的UNIX like逆向工程框架和命令行工具集,它提供了全面的二进制分析能力,
逆向工程开发工具网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考