0x01 前言

本文针对CVE-2019-2725,分三个段落进行阐述,主要涉及到该漏洞的产生原因、相关知识与利用方法三个方面。同时这也是我自己的学习笔记,如果需要快速了解该漏洞的成因以及相关exp,请点这里移步参考链接。

0x02 测试环境

系统:Win7 x64 SP1 (vmware虚拟机)
JDK版本:jdk1.7.0_21 (jdk7u21)
weblogic版本: WebLogic Server 10.3.6.0.171017 PSU Patch for BUG26519424 TUE SEP 12 18:34:42 IST 2017 WebLogic Server 10.3.6.0.180417 PSU Patch for BUG27395085 THU FEB 21 18:34:42 IST 2018 (也就是打了 CVE-2017-10271和CVE-2018-2628的补丁,mmp花了我一上午时间,补丁找了很久而且还可能和之前的补丁有冲突,需要补丁的评论)
IDE: IntelliJ IDEA 2019.1.2 (Ultimate Edition) 远程调试
虚拟机IP:192.168.174.130 (下面会用到)
IDEA远程调试方法可以点击这里参考。

0x03 概述

URL触发点:
http://192.168.174.130:7001/_async/AsyncResponseService
漏洞组件:
wls9_async_response.war
漏洞原理:
该组件支持对传入的SOAP数据包进行解析,解析过程中触发 XMLDecoder 操作导致反序列化漏洞的产生,关于xml反序列化漏洞,请参考这篇文章

0x04 相关知识

1、SOAP

  1. 是什么?
    SOAP全称是Simple Object Access Protocol,中文名称是简单对象访问协议,是一种简单的基于XML的协议。SOAP的载体是HTTP,使得应用程序可以通过HTTP来交换数据。
  2. 为什么?
    刚接触SOAP的时候也在想为什么要用SOAP,这玩意和XML有啥区别,还不如JSON方便,虽然说做安全的可能不必要想这么多,只要能搞洞就完事了。但是我还是总结了下,做个不恰当的比方,XML就像是一种语言,就拿英语来说好了,不同地区的人只要会英语就能交流。而SOAP更像是论文格式,虽然都是英文,但是必须要根据固定的格式走,先写摘要,然后分板块来阐述自己的研究内容,最后总结给出参考文献,这就是一套标准,如果没有这套标准那么我们在看论文的时候估计要痛苦死了。(有异议的可以评论指出,我都会看)
  3. 怎么用?
    SOAP的格式规范可以点击这里查看。同时SOAP也分1.1规范和1.2规范,有些地方的定义不尽相同。
    对于我们想要请求的接口,我们需要使用POST方法来发送SOAP数据,并将HTTP Header中的Content-Typr置为text/xml,同时设置SOAPAction头,或者直接将Content-Type设置为application/soap+xml。

0x05 详细分析

1、POC选择

由于打了补丁,需要绕过补丁的POC,使用github上面的EXP弹计算器当作POC,项目地址点击这里

2、执行路径追踪

Class:weblogic.work.ExecuteThread
Method:run
这个应该是weblogic在监听到请求后开始处理的函数,调用 weblogic.work.execute函数对监听到的请求处理。接下来是一连串调用,直到进入相应的servlet对HTTP包进行处理。
一直到进入servlet的service方法的调用链,这部分东西不必要费太大的精力去分析。
Class:weblogic.wsee.server.servlet.BaseWSServlet
method:service
调用 BaseWSServlet 中的service方法进行处理,这里面进行了一些有关HTTP参数的校验,例如是否必须使用https等等
Class:weblogic.wsee.server.servlet.BaseWSServlet
method:service
这里判断如果需要对请求进行校验的话,则进行校验,校验通过调用BaseWSServlet.AuthorizedInvoke这个类的run方法。可以看出BaseWSServlet.AuthorizedInvoke是BaseWSServlet中的一个内部静态类。
Class:weblogic.wsee.server.servlet.BaseWSServlet.AuthorizedInvoke
method:run
这个内部类中对该 BaseWSServlet 中的Processor列表中的每一个Processor进行处理。这些Processor分别是
这7种Processor是 BaseWSServlet所特有的,可以从下图中看出,是使用ProcessorFactory工厂方法获得一个实例,然后调用getProcessorList来进行获取的。
Class:weblogic.wsee.server.servlet.BaseWSServlet.AuthorizedInvoke
method:getProcessorList
Class:weblogic.wsee.server.servlet.ProcessorFactory
Method:getProcessorList
这7种Processor里面包含了对于不同类型的请求处理的方法。例如当我们传入SOAP数据包的时候,将会返回SoapProcessor的结果,当我们只是通过http协议访问 http://192.168.174.130:7001/_async/AsyncResponseService 时,会返回IndexPageProcessor处理的结果。这里可以将这个当作对于传入连接种类的不同处理器。接下来我们需要关注SoapProcessor的实现。
Class:weblogic.wsee.server.servlet.SoapProcessor
Method:process
在这个方法中显示校验了请求是否是POST请求,如果是则进入下一步处理。
Class:weblogic.wsee.server.servlet.SoapProcessor
Method:handlePost
在这个函数中,通过WsPort首先获取了请求数据包的SOAP协议版本,根据云影实验室的分析,他们认为这里的getEndpoint方法对SOAP消息中的根元素进行了解析并关联了其中soap的命名空间,而根据我得观察这里只是获取了BaseWSServlet中的endpoint的值,而endpoint的值是在 BaseWSServlet 进行init初始化的时候就确定下来的。
接下来继续跟进,创建了个SoapServerConnection实例,通过调用WsSkel的invoke方法并传入该 SoapServerConnection 与WsPort继续进行处理。
Class:weblogic.wsee.ws.WsSkel
Method:invoke
在这个方法中首先建立了一个线程,并实例化了ServerDispatcher类,然后通过setWsPort指定WebService的相关信息
WsPort中的信息
Class:weblogic.wsee.ws.dispatch.server.ServerDispatcher
Method:dispatch
在dispatch函数中进行很多处理,观察其对WsPort中的handlerList进行了处理,HandlerList共计定义了21种Handler,这21种handler的获取方法我没法跟出来,以后有空会补上,不过不影响继续分析,接下来重点关注第17个handler,也就是WorkAreaServerHandler
WsPort.HandleChain的21种Handler
Class:weblogic.wsee.async.WorkAreaServerHandler
Method:handleRequest
在WorkAreaServerHandler的handleRequest方法中, 通过WlMessageContext对象var2获取传入的MessageContext ,然后获取SOAP请求的Header,并校验其是否存在,如果存在则新建一个WorkContextXmlInputAdapter适配器,并将刚才获得的Header转换为InputStream传入,进行下一步处理。
Class:weblogic.workarea.WorkContextMapImpl
Method:receiveRequest
Class:weblogic.workarea.WorkContextMapImpl
Method:getMap
Class:weblogic.workarea.WorkContextLocalMap
Method:receiveRequest
Class:weblogic.workarea.spi.WorkContextEntryImpl
Method:readEntry
Class:weblogic.wsee.workarea.WorkContextXmlInputAdapter
Method:readUTF
这部分就像云影实验室说的那样“经内部getMap() -> receiveRequest() -> readEntry() 方法处理后,将上述Content字段传入至WorkContextXmlInputAdapter类的readUTF()方法中 ”,然后这里出现了久违的xmlDecoder.readObject方法,到此为止就是漏洞从输入点到sink点的全过程。

0x06 利用构造

1、绕过补丁

最开始的时候该漏洞由于和 CVE-2017-10271 的漏洞触发点是相同的,所以有了很多基于 CVE-2017-10271 的poc,在没有打补丁的情况下这些poc时能够使用的,但是打了补丁则会在 WorkContextXmlInputAdapter 中validate方法对传入数据中的 object,new,method,array,void 字段进行过滤,如下图所示
Class:weblogic.wsee.workarea.WorkContextXmlInputAdapter
Method:validate
该部分的绕过我觉得云影实验室已经讲的够透彻了,引用下“本次反序列化漏洞绕过以往补丁的关键点在于利用了Class元素指定任意类名,因为CVE-2017-10271补丁限制了带method属性的void元素,所以不能调用指定的方法,而只能调用完成类实例化过程的构造方法。在寻找利用链的过程中发现UnitOfWorkChangeSet类构造方法中直接调用了JDK原生类中的readObject()方法,并且其构造方法的接收参数恰好是字节数组,这就满足了上一个补丁中array标签的class属性值必须为byte的要求,再借助带index属性的void元素,完成向字节数组中赋值恶意序列化对象的过程,最终利用JDK 7u21反序列化漏洞造成了远程代码执行。通过巧妙的利用了void、array和Class这三个元素成功的打造了利用链,再次完美的绕过了CVE-2017-10271补丁限制,本次漏洞的发现进一步证明了依靠黑名单机制是一种不可靠的防护措施。”

2、普适性

云影实验室的方法当然只是针对jdk<=7u21和weblogic 10.3.6来说的,但是还存在其他相当一部分jdk和weblogic版本不同的,所以在bithack上我发现了一篇很好的利用文章,详细介绍了各个版本的利用方法,点击这里查看。

3、一些细节

为什么需要加上这部分
<wsa:Action>xx</wsa:Action><wsa:RelatesTo>xx</wsa:RelatesTo>
Class:weblogic.wsee.async.AsyncResponseHandler
Method:handleRequest
Class:weblogic.wsee.async.ServerAddressingHandler
Method:handleRequest
上述两个Handler在处理时会对Action和RelatesTo进行获取,如果没有会抛出错误。

0x07 参考文献

  1. WebLogic RCE(CVE-2019-2725)漏洞之旅
  2. Weblogic反序列化远程代码执行漏洞(CVE-2019-2725)分析报告
  3. Weblogic wls9_async_response 反序列【CNVD-C-2019-48814】
  4. CVE-2019-2725/CNVD-C-2019-48814 绕过CVE-2017-10271补丁
  5. CVE-2019-2725/CNVD-C-2019-48814第二弹——JNDI
  6. CVE-2019-2725/CNVD-C-2019-48814第三弹——通杀
  7. iceMatcha/CNTA-2019-0014xCVE-2019-2725
  8. Weblogic 远程命令执行漏洞分析(CVE-2019-2725)及利用payload构造详细解读
  9. weblogic XMLDecoder反序列化漏洞-CVE-2017-10271
  10. XMLDecoder解析流程分析
  11. 廖新喜 :Weblogic CVE-2019-2725 分析报告
  12. 为什么要学习SOAP/WebService?
  13. WebLogic wls9-async组件RCE分析(CVE-2019-2725)

Leave a Comment

电子邮件地址不会被公开。 必填项已用*标注