我希望能够提取一个 tar 文件,以便所有提取的文件都放置在某个前缀目录下。 tar 文件写入外部目录的任何尝试都会导致提取失败。
正如您可能想象的那样,这样我就可以安全地提取不受信任的 tar 文件。
我怎样才能用 GNU 做到这一点tar
?
我想出了:
tar --exclude='/*' --exclude='*/../*' --exclude='../*' -xvf untrusted_file.tar
但我不确定这是否足够偏执。
答案1
你根本不需要偏执。 GNU——tar
事实上任何过去 30 年左右编写的精心设计的tar
程序 —— 默认情况下,将拒绝提取 tarball 中以斜杠开头或包含..
元素的文件。
您必须竭尽全力强制现代tar
程序提取此类潜在恶意的 tarball:GNU 和 BSD 都tar
需要-P
选项来禁用此保护。参见 参考资料 部分绝对文件名在 GNU tar 手册中。
-P
不过,POSIX 并未指定该标志,因此其他tar
程序可能有不同的方式来处理此问题。例如,Schily 工具star
程序使用-/
和-..
禁用这些保护。
您可能考虑向简单命令添加的唯一内容tar
是一个-C
标志,以强制其将内容提取到安全的临时目录中,因此您不必先到cd
那里。
旁白:
答案2
使用 GNU tar,这很简单
tar -xvf untrusted_file.tar
在一个空目录中。 GNU tar 在提取时会自动去除前导/
成员名称,除非使用--absolute-names
选项。 GNU tar 还检测何时使用../
会导致文件被提取到顶级目录之外,并将这些文件放入顶级目录中,例如,组件foo/../../bar/qux
将在顶级目录中提取,bar/qux
而不是bar/qux
在顶级目录的父目录中提取。 GNU tar 还负责指向顶级目录之外的符号链接,例如,foo -> ../..
并且foo/bar
不会导致bar
在顶级目录之外提取。
请注意,这仅适用于(足够新的版本)GNU tar(以及一些其他实现,例如 *BSD tar 和 BusyBox tar)。其他一些实现没有这样的保护。
由于符号链接的存在,您使用的保护是不够的:存档可能包含指向树外部目录的符号链接并提取该目录中的文件。纯粹根据成员名称无法解决该问题,您需要检查符号链接的目标。
请注意,如果您提取到已包含符号链接的目录,则保证可能不再成立。
答案3
为了涵盖其他答案没有涵盖的几点:
首先,在解压之前查看文件中的内容:
tar -tvf untrusted_tar_file.tar
如果其中有任何您不信任或不想提取的内容,请不要提取 tarball。
- 其次,以非根用户身份提取 tarball,该用户仅对要将 tarball 提取到的一个目录具有写入权限。例如,从非 root 用户的主目录中提取 tarball。