前言

之前比较懒一直没安装契约锁进行审计最近正好爆出挺多这个产品的漏洞,于是抽空分析一下近期的漏洞为后续挖掘打基础。这篇文章主要写pdfverifier接口的漏洞以及这个地方补丁被多次绕过的分析。

pdfverifier漏洞分析利用

下面分析使用的版本为Linux下的4.3.4版本,契约锁启动后会开启三个端口分别对应下面三个服务

  • 电子签约签署平台:9180

  • 电子签约管理控制台:9181

  • 电子签约开放平台:9182

官方建议只对外开放9180端口pdfverifier接口的漏洞便是在这个端口,对应的jar包为privapp.jar。将这个jar包拿出来分析发现无法解压



使用010Editor打开



发现前面一大段为bash脚本直接将前面的字符删除即可成功解压。解压以后发现BOOT-INF\lib\下只有少数的jar包,简单查看目录结构确定其他依赖应该在/opt/qiyuesuo/libs目录下于是直接将/opt/qiyuesuo/libs全部复制到BOOT-INF\lib\然后idea打开即可。这里有个需要注意的问题当我们没把spring的依赖放入libidea的两下shift查看接口是没有用的,必须存在spring的依赖他才会扫描得到接口。根据classes目录结构很快可以注意到com.qiyuesuo.config.PrivappConfigurer定义了过滤器和白名单接口。



pdfverifier接口正好在里面直接两下shift定位到接口的实现方法





获取扩展名以后传入com.qiyuesuo.api.PdfVerifierController#doVerify



当扩展名为ofd时进入net.qiyuesuo.common.ofd.verify.GjzwOfdVerifyHandler#verify





最后对文件进行了解压操作



这里没有判断目录穿越的情况,所以可以解压文件目录穿越写入任意文件到任意目录。但是这个服务是springboot不能给通过写webshellRCE,可以想到的几种比较通用的办法写模版文件、往JDK的某些的地方写文件然后初始化类、写计划任务。写模板文件的话好像没有配置了视图模板解析,往JDK的某些的地方写文件可能不太通用,写计划任务只针对Linux且没有权限因为他这里是用qiyuesuo账号起的服务。这里如果以前下载过qys的补丁的话就会想到他的补丁是热加载的。





所以我们可以通过覆盖/opt/qiyuesuo/security/private-security-patch.jar文件进行代码执行,虽然知道了可以通过覆盖这个文件来RCE但是我们还需要知道怎么构造这个jar包才会执行到我们的恶意代码。根据补丁安装说明可以知道主要逻辑应该在private-security-loader-1.0.0.jar里点开这个jar第一个类就是com.qiyuesuo.security.patch.loader.SecurityLibManager



这里很明显就是触发热加载的地方,检测到hash值发生变化就会进行reload以及registerQVDLogic



这里加载jar包





加载class



当全类名前缀为com.qiyuesuo.security.patch.filter.logic时会实例化这个类此时可以执行到类的静态代码块,所以我们只需要往正常的private-security-patch.jar里加入com.qiyuesuo.security.patch.filter.logic.xxx 然后在静态代码块里执行恶意代码即可。于是我使用jmg生成了一个这样的内存马注入器类名为com.qiyuesuo.security.patch.filter.logic.ofdrce进行漏洞利用发现没有成功,经过调试发现我本地的private-security-loader-1.0.0.jar可能和我上传的private-security-patch.jar版本不对应



实例化com.qiyuesuo.security.patch.filter.logic包里某个类调用com.qiyuesuo.security.patch.common.util.SecurityResourceOperator类里的方法时因为其还没有实例化导致空指针异常退出,解决办法是将恶意类命名为com.qiyuesuo.security.patch.filter.logic.AAAA这样的话最开始实例化的就是我们的恶意类。

生成恶意类



将恶意类加入正常的private-security-patch.jar中(注意有的压缩软件直接拉文件进jar包会导致错误)



制作恶意压缩文件LINUX也可使用/proc/self/cwd/security/目录更加靠谱,windows可尝试/qiyuesuo/security/目录



构造数据包上传



等待几秒钟成功实例化我们的恶意类



成功打入内存马

1.3.2补丁绕过

这个漏洞最初由1.3.2版本补丁修复,补丁关键代码如下



先获取URL然后判断是否等于PDFVERIFIER_URL_LIST里的某个值ENABLE默认为true且请求方法为POST则使用PdfverifierPreventWrapper包装request我们这里按照补丁绕过顺序来分析所以直接对比1.3.2和1.3.3补丁即可发现绕过点



绕过点位于包装类的getParts方法,当spring解析上传格式时会调用getParts方法此时会调用到com.qiyuesuo.security.patch.filter.wrapper.PdfverifierPreventWrapper#getParts而这个方法里面获取文件名和spring获取文件名存在差异。spring支持将整个文件名URL编码org.springframework.web.multipart.support.StandardMultipartHttpServletRequest#parseRequest



这个地方会对整个filename进行URL解码



1.3.2版本补丁使用的org.apache.catalina.core.ApplicationPart#getSubmittedFileName不支持将整个文件名URL解码



从而在filename.toLowerCase().endsWith(REGEX)时判断失败所以可以直接使用URL编码的文件名绕过补丁

直接上传ofd被拦截



使用URL编码绕过补丁



其实这个地方也修复了MIME编码加URL编码双重编码的绕过

1.3.3-1.3.5补丁绕过

我下载了1.3.3之后的所以补丁,1.3.4-1.3.5补丁和pdfverifier相关的改动感觉不是在修复绕过或者说是其他接口的zip slip漏洞修复。所以这里我们直接对比1.3.5和1.3.6补丁



增加了一个removeEndSlash方法用于移除末尾的斜杠,其实这个绕过我感觉比上面的绕过更容易想到。我们先看他是如何获取uri



通过getRequestURI获取



将双斜杆替换为单斜杠



这里使用的等于来判断



虽然用了getRequestURI获取uri但是不能使用下面这类绕过

  • /api/;/pdfverifier

  • /api/./pdfverifier

  • ///api/pdfverifier

因为他前面有个补丁com.qiyuesuo.security.patch.filter.logic.DangerUrlPreventLogic#doQvdLogic是专门判断这类uri的,这里就需要使用spring的一个特性在路由后面添加斜杠一样可以访问到,所以使用以下POC成功绕过补丁

1.3.6补丁绕过

直接对比1.3.6和1.3.7补丁



这里修改了removeDuplicateSlash方法移除双斜杆改为了移除所有且将/+都替换为/,所以这里的绕过应该是三斜杠绕过,不过按道理三斜杠会被com.qiyuesuo.security.patch.filter.logic.DangerUrlPreventLogic#doQvdLogic检测到,为什么可以绕过呢,因为正好末尾的///先经过一次removeDuplicateSlash变为//再经过一次removeEndSlash变为了/正好可以过com.qiyuesuo.security.patch.filter.logic.DangerUrlPreventLogic#doQvdLogic检测,所以绕过POC如下

1.3.7补丁绕过

直接对比1.3.7和1.3.8补丁



这里改动比较大的地方在hasPathTraversal方法里,但是乍一看看不出什么问题。

这里移除了(entry = zis.getNextEntry()) == null的判断,改为了使用和后面pdfverifier接口解压相同的代码,于是猜测有一种办法可以导致zis.getNextEntry()== null,而后面的解压代码依然可以解压。跟入getNextEntry发现会对文件头做判断如果不是zip文件头则返回NULL



而后面解压代码没有使用getNextEntry于是直接在压缩文件头部添加\r\n发现此时zis.getNextEntry()== null而解压代码依然可以解压这个压缩文件,所以这个补丁的bypass即为在压缩文件头部添加\r\n



我这里测试绕过成功但是内存马没打上后面看了下又是之前的原因实例化com.qiyuesuo.security.patch.config.logic.SecurityPropertiesConfigLogic的时候报错了而这个类的顺序是在我们之前内存马顺序之前所以还是建议内存马使用com.qiyuesuo.security.patch.config.logic.AAAAA最为靠谱,替换内存马类名后成功注入内存马。

总结

这个漏洞本身其实比较简单,覆盖补丁热加载来RCE值得学习,后续的多次补丁绕过也挺有意思。所以说挖洞的话还是需要多分析历史漏洞说不定就绕过了挖个新的RCE呢。


本文仅供安全研究和学习使用,由于传播、利用此文档提供的信息而造成任何直接或间接的后果及损害,均由使用本人负责,公众号及文章作者不为此承担任何责任。

契约锁pdfverifier远程代码执行漏洞攻防绕过史的更多相关文章

  1. 【预警通告】Apache Struts2 远程代码执行漏洞

    Apache Structs2的Jakarta Multipart parser插件存在远程代码执行漏洞,漏洞编号为CVE-2017-5638.攻击者可以在使用该插件上传文件时,修改HTTP请求头中的 ...

  2. Spring框架的反序列化远程代码执行漏洞分析(转)

    欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...

  3. Apache Struts 远程代码执行漏洞(CVE-2013-4316)

    漏洞版本: Apache Group Struts < 2.3.15.2 漏洞描述: BUGTRAQ ID: 62587 CVE(CAN) ID: CVE-2013-4316 Struts2 是 ...

  4. MongoDB ‘conn’Mongo 对象远程代码执行漏洞

    漏洞名称: MongoDB ‘conn’Mongo 对象远程代码执行漏洞 CNNVD编号: CNNVD-201307-497 发布时间: 2013-07-25 更新时间: 2013-07-25 危害等 ...

  5. Struts2再爆远程代码执行漏洞

    Struts又爆远程代码执行漏洞!在这次的漏洞中,攻击者可以通过操纵参数远程执行恶意代码.Struts 2.3.15.1之前的版本,参数action的值redirect以及redirectAction ...

  6. struts2之高危远程代码执行漏洞,可造成服务器被入侵,下载最新版本进行修复

          Struts2 被发现存在新的高危远程代码执行漏洞,可造成服务器被入侵,只要是Struts2版本 低于 2.3.14.3 全部存在此漏洞.目前官方已经发布了最新的版本进行修复.请将stru ...

  7. 【漏洞公告】CVE-2017-12615/CVE-2017-12616:Tomcat信息泄漏和远程代码执行漏洞

    2017年9月19日,Apache Tomcat官方确认并修复了两个高危漏洞,漏洞CVE编号:CVE-2017-12615和CVE-2017-12616,该漏洞受影响版本为7.0-7.80之间,在一定 ...

  8. PHPMailer < 5.2.18 远程代码执行漏洞(CVE-2016-10033)

    PHPMailer < 5.2.18 Remote Code Execution 本文将简单展示一下PHPMailer远程代码执行漏洞(CVE-2016-10033)的利用过程,使用的是别人已经 ...

  9. 隐藏17年的Office远程代码执行漏洞(CVE-2017-11882)

    Preface 这几天关于Office的一个远程代码执行漏洞很流行,昨天也有朋友发了相关信息,于是想复现一下看看,复现过程也比较简单,主要是简单记录下. 利用脚本Github传送地址 ,后面的参考链接 ...

  10. phpcms2008远程代码执行漏洞

    phpcms2008远程代码执行漏洞 描述: 近日,互联网爆出PHPCMS2008代码注入漏洞(CVE-2018-19127).攻击者利用该漏洞,可在未授权的情况下实现对网站文件的写入.该漏洞危害程度 ...

随机推荐

  1. 『Plotly实战指南』--在金融数据可视化中的应用(上)

    在当今复杂多变的金融市场中,金融数据分析的重要性不言而喻. 无论是投资者.金融机构还是研究人员,都需要通过对海量金融数据的分析来洞察市场趋势.评估风险并做出明智的决策. 据彭博社统计,专业投资者平均需 ...

  2. 【翻译】Processing系列|(二)安卓模式的安装使用及打包发布

    上一篇:[翻译]Processing系列|(一)简介及使用方法 下一篇:[翻译] Processing系列|(三)安卓项目构建 我的目的是在学习完成之后写出一个安卓程序,所以第二篇就是Processi ...

  3. 遇到的问题之“使用get请求时,请求参数中存在#导致后端request获取不到值”

    一.问题 使用get请求时,请求参数中存在#导致后端request获取不到值 发出参数带#的请求 后端接收不到SKU的值,连后面platformId的值都没有了 二.原因 1.有些符号[参数包含有特殊 ...

  4. centos6分区要点

    安装centos6系统时,为了以后能够扩展存储,分区时要注意几点: 1.boot引导分区要选固定分区类型存储,大小是500M 2.其余分区全部做成物理卷lvm  pyshiic类型存储 3.在这个物理 ...

  5. Torch-Pruning工具箱

    Torch-Pruning 通道剪枝网络实现加速的工作. Torch pruning是进行结构剪枝的pytorch工具箱,和pytorch官方提供的基于mask的非结构化剪枝不同,工具箱移除整个通道剪 ...

  6. 一篇文章给你讲清楚运筹优化到底怎么学!基于 SCIP Optimization Suite 的运筹优化入坑教程

    [!abstract] 本文笔者用暴躁而又不失严谨性的语言,从优化问题的背景入手,强调了针对实际的工程问题开展的优化建模方法和学校教学内容之间的偏差,并围绕优化建模到底应该怎么学的问题,讲解了如何下载 ...

  7. golang unsafe遇上字符串拼接优化导致的bug

    最近料理老项目的时候被unsafe坑惨了,这里挑一个最不易察觉的错误记录一下. 这个问题几乎影响近几年来所有的go版本,为了方便讨论我就用最新版的1.24.3做例子了. 线上BUG 我们有一个收集集群 ...

  8. 【公众号搬运】React-Native开发鸿蒙NEXT

    .markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...

  9. 远程登录Mysql,命令行登录Mysql的方法

    1.本地登录MySQL命令:mysql -u root -p   //root是用户名,输入这条命令按回车键后系统会提示你输入密码2.指定端口号登录MySQL数据库将以上命令:mysql -u roo ...

  10. Flannel相关问题记录

    k8s的Pod无法分配IP 报错信息 E0222 07:22:36.762074 83 remote_runtime.go:113] RunPodSandbox from runtime servic ...