1.zip slip问题

zip slip文件

一、简述

压缩有个 zip slip问题。简单来说现在有这两个目录:
├── test
│ └── evil.zip //bad virus
└── test1
└── demo.txt //hello

  • test目录下有我们想解压缩 evil.zip文件。 test1目录是我们不想对外暴露的个人文件夹。
  • evil.zip里是一个 原名为"…/test1/demo.txt"的文件。压缩后文件名并没有丢失(可以看成是存到zip{}这个结构体里了),解压缩的时候就会获取原始文件名"…/test1/demo.txt",然后解压的时候,就会覆盖test1文件夹下的demo.txt,把原文件内容“hello”变成“bad virus”。就篡改了用户的文件。
  • 试想一下,test1文件下是一个可执行文件呢? 这样的文件被替换后,当执行这个可执行文件时,电脑就可能会中病毒。
  • 注:并不能替换根目录/或者/etc目录下的文件,因为会爆Permisson Deny错误。
    解决这个问题的办法是,不信任原始的文件名,对其进行校验。 并且校验他的父目录是不是test即可。

怎么解决这个问题呢? 下面是go和java代码。

if (!fileName.contains("..") && !f.getCanonicalPath().startsWith(destFile.getCanonicalPath())) {}
if !strings.HasPrefix(fileName, zipFileBase) {
    return errors.New("invalid file path")
}

二、zip slip问题 详述

2.1 问题介绍

ZipSlip攻击是一种利用压缩文件中的目录遍历漏洞来覆盖系统中的任意文件的攻击方式,通常会导致远程命令执行。攻击者通过构造一个压缩文件条目中带有…/的压缩文件,上传后交给应用程序进行解压,由于程序解压时没有对文件名进行合法性的校验,而是直接将文件名拼接在待解压目录后面,导致可以将文件解压到正常解压缩路径之外并覆盖可执行文件、配置文件或其他敏感文件。ZipSlip攻击影响多种编程语言和压缩文件格式,例如tar、jar、war、cpio、apk、rar、7z等。为了防止ZipSlip攻击,应用程序在解压压缩文件时应该对文件路径进行验证,避免目录遍历。

2.1代码示例

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.zip.ZipOutputStream;


public class Zip {

    public static void main(String[] args) throws IOException {
        String srcName = "/Users/Mac/Desktop/zip_slip/test/test.txt";
        //第一个参数是需要压缩的源路径;第二个参数是压缩文件的目的路径,这边需要将压缩的文件名字加上去
        compress(srcName, "/Users/Mac/Desktop/zip_slip/test/evil.zip");
    }

    /**
     * 压缩文件
     *
     * @param srcFilePath  压缩源路径
     * @param destFilePath 压缩目的路径
     */
    public static void compress(String srcFilePath, String destFilePath) {
        File src = new File(srcFilePath);
        if (!src.exists()) {
            throw new RuntimeException(srcFilePath + "不存在");
        }
        File zipFile = new File(destFilePath);
        try {
            FileOutputStream fos = new FileOutputStream(zipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);
            String baseDir = "../test/";
            compressbyType(src, zos, baseDir);
            zos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 按照原路径的类型就行压缩。文件路径直接把文件压缩,
     *
     * @param src
     * @param zos
     * @param baseDir
     */
    private static void compressbyType(File src, ZipOutputStream zos, String baseDir) {
        if (!src.exists())
            return;
        System.out.println("压缩路径" + baseDir + src.getName());
        compressFile(src, zos, baseDir);
    }

    /**
     * 压缩文件
     */
    private static void compressFile(File file, ZipOutputStream zos, String baseDir) {
        if (!file.exists())
            return;
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            zos.putNextEntry(entry);
            int count;
            byte[] buf = new byte[1024];
            while ((count = bis.read(buf)) != -1) {
                zos.write(buf, 0, count);
            }
            bis.close();
        } catch (Exception e) {
        }
    }
}

class Unzip {
    public static void main(String[] args) throws IOException {
        //解压zip的包
        String fileAddress = "/Users/Mac/Desktop/zip_slip/test/evil.zip";
        //zip文件解压路
        String unZipAddress = "/Users/Mac/Desktop/zip_slip/test/";
        //去目录下寻找文件
        File file = new File(fileAddress);
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(file, "GBK");//设置编码格式
        } catch (IOException exception) {
            exception.printStackTrace();
            System.out.println("解压文件不存在!");
        }
        Enumeration e = zipFile.getEntries();
        while (e.hasMoreElements()) {
            ZipEntry zipEntry = (ZipEntry) e.nextElement();
            System.out.println(zipEntry.getName());

            File f = new File(unZipAddress + zipEntry.getName());
            f.getParentFile().mkdirs();
            f.createNewFile();
            InputStream is = zipFile.getInputStream(zipEntry);
            FileOutputStream fos = new FileOutputStream(f);
            int length = 0;
            byte[] b = new byte[1024];
            while ((length = is.read(b, 0, 1024)) != -1) {
                fos.write(b, 0, length);
            }
            is.close();
            fos.close();
        }
        if (zipFile != null) {
            zipFile.close();
        }
    }
}

只看UnZip类就可以。本来想解压到test文件夹下,结果因为文件名有坑,就导致解压到了test1文件下,并且把test1文件下本来存在的test.txt目录给覆盖了。

上面写Zip类是因为,系统不允许我们创建一个名为 "…/test1/test.txt"的文件,所以就用程序来创建并压缩。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi 2007 Slip是指Delphi 2007集成开发环境(IDE)的升级补丁。Delphi是一种基于Pascal语言的快速应用程序开发工具,用于创建Windows应用程序。Delphi 2007 Slip是由Embarcadero Technologies提供的一项升级补丁,旨在改进Delphi 2007的稳定性和功能。 Delphi 2007提供了许多强大的功能和工具,使开发者能够快速构建可靠的Windows应用程序。然而,在使用过程中可能会遇到一些问题或bug。Delphi 2007 Slip补丁的目的是修复这些问题,提高IDE的性能和稳定性。 Delphi 2007 Slip的主要特点包括: 1. 增强的性能和稳定性:Delphi 2007 Slip补丁修复了一些已知的bug和问题,提高了IDE的性能和稳定性。这意味着开发者可以更加高效地开发和调试他们的应用程序。 2. 新功能的引入:Delphi 2007 Slip还引入了一些新的功能和改进,以提供更好的开发体验。这些新功能可以帮助开发者更方便地处理一些常见的开发任务,提高开发效率。 3. 兼容性和互操作性:Delphi 2007 Slip与其他Delphi版本和相关工具(如数据库和第三方组件)的兼容性得到了改进。这意味着开发者可以更容易地迁移他们的项目或与其他开发者进行协作。 4. 文档和技术支持:Delphi 2007 Slip补丁还提供了相关文档和技术支持,帮助开发者更好地理解和使用Delphi 2007的新功能和改进。 总结而言,Delphi 2007 Slip是一项修复和改进Delphi 2007 IDE的补丁。它提供了更好的性能和稳定性、新功能的引入、兼容性和互操作性的提升,以及相关文档和技术支持。对于使用Delphi 2007开发Windows应用程序的开发者来说,安装Delphi 2007 Slip是一个值得考虑的升级选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值