一、zipSlip
Zip Slip是一个广泛存在的关键存档提取漏洞,该漏洞允许攻击者在系统中任意写文件,尤其是会导致远程命令执行。
利用条件:
1.有恶意压缩文件(恶意用户可以构造);
2.对解压路径不会执行检查或检测不到位。
测试代码如下:
1 | private static void unZip() throws IOException { |
构造恶意zip包:
1 | import zipfile |
生成恶意包后,执行上面java代码,发现zip包并没有解压到指定的路径,实现了目录穿越。
debug运行一下。可看到zipEntry.getName()方法并未对输入的名字做任何校验,直接拼接到解压路径中,以通过“../”的方式进行目录穿越
二、zipBomb
主要在存在上传功能且对上传文件有解压动作的地方,如果校验不严,可能导致压缩炸弹,导致dos攻击。
准备:
通过脚本构造恶意的压缩文件:
1 | import zlib |
只起演示效果,所以生成了500个100k的,可看到100k压缩包解压后的文件夹变成50m了。只扩大了500倍。
测试代码:
出现该漏洞的大多数是以下两情况,
1.完全无校验
2.只对压缩文件大小做校验。
此处以第二种情况为例,测试代码如下:
1 | private static void unZipBomb() throws IOException { |
得到压缩文件大小,
这里,我们可以通过修改压缩包的大小实现绕过,用二进制文件打开zip压缩包,如下图所示:
zip结构如下,这里,我们只对“uint frUncompressedSize”字段感兴趣。
- struct ZIPFILERECORD record :文件名;
- uint frUncompressedSize:解压后的文件大小
将100000全部替换成100.重新执行java测试文件:
修复方式:
对文件名、解压文件大小和个数都进行检测:
1.除了在解压每个条目之前对其文件名进行校验;
2.while循环代码检查从zip存档文件中解压出来的每个文件条目的大小是否大于100MB;
3.最后计算从存档文件中解压出来的文件条目总数,如果超过1000个,则抛出异常。