我正在尝试将用户提交的zip和tar文件解压到一个目录中。zipfile的extractall方法(类似于tarfile的extractall)的文档说明,路径可能是绝对的,也可能包含目标路径之外的..
路径。相反,我可以自己使用extract
,比如:
some_path = '/destination/path'
some_zip = '/some/file.zip'
zipf = zipfile.ZipFile(some_zip, mode='r')
for subfile in zipf.namelist():
zipf.extract(subfile, some_path)
这安全吗?在这种情况下,存档中的文件是否可能在some_path
之外结束?如果是,我如何才能确保文件永远不会出现在目标目录之外?
将zipfile复制到空目录。然后使用
os.chroot
使该目录成为根目录。然后打开拉链。或者,可以使用
-j
标志调用unzip
本身,该标志忽略目录:注意:从Python2.7.4开始,这对于ZIP存档是不存在问题的。答案底部的细节。这个答案的重点是tar档案。
要找出路径真正指向的位置,请使用
os.path.abspath()
(但请注意符号链接作为路径组件的注意事项)。如果用abspath
规范化来自zipfile的路径,并且它确实不包含当前目录作为前缀,那么它指向它的外部。但您还需要检查从存档中提取的任何符号链接的值(tarfiles和unix zipfiles都可以存储符号链接)。如果您担心一个众所周知的“恶意用户”会故意绕过您的安全性,而不是一个只在系统库中安装自身的应用程序,那么这一点非常重要。
这就是前面提到的警告:如果沙盒已经包含指向目录的符号链接,那么
abspath
将被误导。即使是指向沙盒内的符号链接也可能是危险的:符号链接sandbox/subdir/foo -> ..
指向sandbox
,因此应该禁止路径sandbox/subdir/foo/../.bashrc
。最简单的方法是等到前面的文件被提取并使用os.path.realpath()
。幸运的是,extractall()
接受生成器,所以这很容易做到。既然你要求代码,这里有一点解释算法。它不仅禁止将文件提取到沙箱外部的位置(这是请求的位置),还禁止在沙箱内部创建指向沙箱外部位置的链接。我很想知道是否有人能从它身边偷看任何流散的文件或链接。
编辑:从python 2.7.4开始,ZIP存档不存在此问题:方法^{} 禁止在沙盒之外创建文件:
tarfile
类没有经过类似的清理,因此上面的答案仍然适用。使用
ZipFile.infolist()
/TarFile.next()
/TarFile.getmembers()
获取有关存档中每个条目的信息,规范化路径,自己打开文件,使用ZipFile.open()
/TarFile.extractfile()
获取与条目类似的文件,然后自己复制条目数据。相关问题 更多 >
编程相关推荐