jte*_*ace 26 python zip tar zipfile tarfile
我正在尝试将用户提交的zip和tar文件提取到目录中.为zip文件的文档extractall方法(同样用tar文件的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)
Run Code Online (Sandbox Code Playgroud)
这样安全吗?some_path在这种情况下,存档中的文件是否可能在外部结束?如果是这样,我可以通过哪种方式确保文件永远不会出现在目标目录之外?
ale*_*xis 39
注意:从python 2.7.4开始,这对于ZIP存档来说不是问题.答案底部的详细信息.这个答案主要关注tar档案.
要找出路径真正指向的位置,请使用os.path.abspath()(但请注意关于符号链接作为路径组件的警告).如果您与您的zip文件规范的路径abspath,它并没有包含在当前目录作为前缀,它的指向外面.
但是您还需要检查从归档中提取的任何符号链接的值(tarfiles和unix zipfiles都可以存储符号链接).如果您担心会故意绕过您的安全性的众所周知的"恶意用户"而不是仅仅安装在系统库中的应用程序,这一点非常重要.
这就是前面提到的警告:abspath如果您的沙箱已经包含指向目录的符号链接,则会被误导.即使是指向沙箱的符号链接也可能是危险的:符号链接sandbox/subdir/foo -> ..指向sandbox,因此sandbox/subdir/foo/../.bashrc应该禁止路径.最简单的方法是等到先前的文件被提取并使用 os.path.realpath().幸运的是extractall()接受了一台发电机,所以这很容易做到.
既然你要求代码,这里有一点可以解释算法.它不仅禁止将文件提取到沙箱之外的位置(这是请求的位置),还禁止在沙箱内创建指向沙箱外部位置的链接.我很想知道是否有人可以偷偷过去任何流浪文件或链接.
import tarfile
from os.path import abspath, realpath, dirname, join as joinpath
from sys import stderr
resolved = lambda x: realpath(abspath(x))
def badpath(path, base):
# joinpath will ignore base if path is absolute
return not resolved(joinpath(base,path)).startswith(base)
def badlink(info, base):
# Links are interpreted relative to the directory containing the link
tip = resolved(joinpath(base, dirname(info.name)))
return badpath(info.linkname, base=tip)
def safemembers(members):
base = resolved(".")
for finfo in members:
if badpath(finfo.name, base):
print >>stderr, finfo.name, "is blocked (illegal path)"
elif finfo.issym() and badlink(finfo,base):
print >>stderr, finfo.name, "is blocked: Hard link to", finfo.linkname
elif finfo.islnk() and badlink(finfo,base):
print >>stderr, finfo.name, "is blocked: Symlink to", finfo.linkname
else:
yield finfo
ar = tarfile.open("testtar.tar")
ar.extractall(path="./sandbox", members=safemembers(ar))
ar.close()
Run Code Online (Sandbox Code Playgroud)
编辑:从python 2.7.4开始,这对于ZIP存档来说不是问题:该方法zipfile.extract()禁止在沙箱外创建文件:
注意:如果成员文件名是绝对路径,则驱动器/ UNC共享点和前导(后退)斜杠将被剥离,例如:
///foo/bar变为foo/barUnix,并C:\foo\bar变为foo\barWindows.并且".."会删除成员文件名中的所有组件,例如:../../foo../../ba..r成为foo../ba..r.在Windows中,非法字符(:,<,>,|,",?,和*)[被]用下划线(_)代替.
这个tarfile班级没有同样的消毒,所以上面的答案仍然是apllies.
使用ZipFile.infolist()/ TarFile.next()/TarFile.getmembers()获取存档中每个条目的信息,标准化路径,自己打开文件,使用ZipFile.open()/TarFile.extractfile()获取条目的类似文件,并自己复制条目数据。
| 归档时间: |
|
| 查看次数: |
16635 次 |
| 最近记录: |