java slip漏洞复现分析

admin 2024年11月24日12:14:00评论13 views字数 3307阅读11分1秒阅读模式

微信公众号:[念沉凡] 初学安全的小老弟写的,思路来自于https://xz.aliyun.com/t/12081提供的案例。

java zip slip漏洞

zip slip漏洞其实是目录遍历漏洞中的一种,通过服务器或应用程序解压压缩文件来进行攻击。恶意攻击者通过构造一个压缩文件条目路径中带有../的压缩文件,上传给目标服务器并进行解压,如果目标服务器在解压时没有对该压缩文件的文件名进行合法性校验,而是直接将文件名拼接在待解压目录之后,则会导致将该文件解压到正常压缩路径之外并覆盖可执行程序,从而等待系统或用户调用他们实现代码执行,或者是覆盖一些配置文件和敏感文件。

漏洞复现

[下载地址](https://gitee.com/RainyGao/DocSys/releases)

我首先下载了DocSystem的MxsDoc_V2.02.43版本,即最新版本,在后台管理系统的系统管理中进行系统升级操作,传入恶意压缩文件,提示

java slip漏洞复现分析

但文件已经被解压到默认目录下,打开目录发现文件位于正确的位置,甚至文件都没有被解压

java slip漏洞复现分析

怀疑在最新版本上该漏洞已经被修复,于是在室友安装的低版本系统MxsDoc_V2.02.36上进行实验

java slip漏洞复现分析

如果构造一个正常的压缩文件,该文件压缩后默认的储存位置为C:MxsDocdocsystomcatwebappsdocSys.ini

java slip漏洞复现分析

但如果上传一个故意构造的压缩文件其中的恶意代码xxx.jsp则会被解压到C:MxsDocdocsystomcatwebappsDocSystem

java slip漏洞复现分析

攻击思路

我们首先来分析一下这个恶意压缩文件

java slip漏洞复现分析

他的文件路径中出现了两个名为..的文件夹,导致与默认解压文件夹拼接后进行回跳,写入敏感的文件目录中

解压时可构造成异常的文件存储路径

../../DocSystem/XXX.jsp

代码审计

在一个JavaWeb项目中,Controller目录通常用于存放处理请求和响应的控制器类。这些控制器类负责 接收来自前端的请求,然后处理请求参数、调用业务逻辑层进行处理,并最终返回响应结果给前端。 因此要具体分析上述漏洞的原理,应该在Controller文件夹中寻找答案

文件路径如下:

DocSys-DocSys_V2.02.36srccomDocSystemcontroller

java slip漏洞复现分析

根据之前了解到的原理可知,问题出现在解压时对于文件名的合法性没有进行检测,导致路径拼接后将../路径拼入,使得文件解压到了规定路径以外的路径,因此我们在代码审计时着重注意解压和文件拼接的方法 

可疑点如下:

java slip漏洞复现分析

在ManageController类中,找到了升级的部分(如下图 里面存在两个疑点,经过分析 

疑点1-getOriginalFilename()

第一个红色箭头指向的的 getOriginalFilename()方法,我们需要先了解一下这个函数,getOriginalFilename()是MultiparrtFile类中的一个函数,用于换取上传文件的原始文件名

文件名限制 对于getOriginalFilename()方法,文件名的限制主要取决于操作系统,浏览器和服务器等因素。在一些操作系统中,文件名的长度最多为260个字符

总的来说,该方法只是用于获取压缩文件的名称,而没有获取压缩文件的内部文件的名称,因此与该漏洞无关

疑点2-unZip()

第二个红色箭头用到了unZip方法,涉及到解压,因此我们去BaseController文件中审计一下unZip代码,发现问题出在unzip方法 

//BaseController   public static boolean unZip(String path, String savepath)    {     boolean ret = false;      int count = -1;       InputStream is = null;       FileOutputStream fos = null;       BufferedOutputStream bos = null;       File file = new File(savepath);      if(file.exists() == false)      {        file.mkdir(); //创建保存目录       }      ZipFile zipFile = null;       try      {         zipFile = new ZipFile(path,"gbk"); //解决中文乱码问题         Enumeration<?> entries = zipFile.getEntries();         while(entries.hasMoreElements())         {       byte buf[] = new byte[2048];           ZipEntry entry = (ZipEntry)entries.nextElement();           String filename = entry.getName();           boolean ismkdir = false;           if(filename.lastIndexOf("/") != -1){ //检查此文件是否带有文件夹            ismkdir = true;           }           filename = savepath + filename;           if(entry.isDirectory()){ //如果是文件夹先创建            file = new File(filename);            file.mkdirs();             continue;           }           file = new File(filename);           if(!file.exists()){ //如果是目录先创建            if(ismkdir){            new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs(); //目录先创建            }           }           file.createNewFile(); //创建文件           is = zipFile.getInputStream(entry);           fos = new FileOutputStream(file);           bos = new BufferedOutputStream(fos, 2048);           while((count = is.read(buf)) > -1)           {             bos.write(buf, 0, count);           }           bos.flush();           bos.close();           fos.close();           is.close();         }         zipFile.close();         ret = true;      }catch(IOException ioe){         Log.info(ioe);       }finally{          try{          if(bos != null){            bos.close();          }          if(fos != null) {            fos.close();          }          if(is != null){            is.close();          }          if(zipFile != null){            zipFile.close();          }          }catch(Exception e) {            Log.info(e);          }       }       return ret;  } 

该JAVA方法可以解压指定路径的压缩文件,并将其内容保存到指定文件中,代码的具体功能如下:

  • - 该方法有两个参数:要解压的压缩文件文件路径(**path**)和要保存提取文件的目录(savepath)

  • - 方法首先检查保存目录是否存在,如果不存在,则创建该目录 - 然后使用ZIP文件路径创建一个 ZipFile 对象。

  • - 接着使用getEntries()方法遍历ZIP文件中的每个条目。

  • - 对于每个条目,方法检查它是目录还是文件。如果是目录,则在保存目录中创建一个新目录。如果是文件,则在保存目录中创建一个新文件,并将条目的内容写入该文件

    其中最重要的代码如下:

    java slip漏洞复现分析

经过不断的while循环,filename的值为 

/..//../..//../../DocSystem/../../DocSystem/XXX.jsp

当filename为第四行的值时,由于没有过滤 ../ 这样的特殊符号,就会执行下面操作,回退到上级文件夹,再次回退到上级文件夹,创建DocSystem文件夹,将XXX.jsp 写入

补丁diff

而在最新版的MxsDoc_V2.02.43版本中,该漏洞已经被修复,我们再来查看一下最新版的代码进行一个比较,我们发现在该版本中的unZip方法已经被修改,增加了对..字符路径的规则限制

java slip漏洞复现分析

原文始发于微信公众号(念沉凡):java slip漏洞复现分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月24日12:14:00
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   java slip漏洞复现分析https://cn-sec.com/archives/1789797.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息