更多资讯和分析文章请关注银河安全实验室微信公众号(Galaxy-Lab)及网站(http://galaxylab.com.cn)
近日, Oracle 公司发布了安全警报( Oracle Security Alert Advisory - CVE-2019-2725 ),修复了此前国家信息安全漏洞共享平台披露的 WebLogic 反序列化远程代码执行漏洞( CNVD-C-2019-48814 )。由于补丁发布已经有一段时间,我们将对该漏洞进行详细分析。
注意本文内容仅用于学习与研究,请勿非法利用。
---------------------------------------------------------
CNVD-C-2019-48814
CVE-2019-2725
漏洞位于 Weblogic 内置的“ wls9_async_response ”组件与“ wls-wsat ”组件。漏洞产生的根本原因是 CVE-2017-10271 的补丁可被绕过,导致允许攻击者构造恶意 SOAP 消息内容进行 XMLDecoder 反序列化。由于互联网上关于 CVE-2017-10271 漏洞的分析文章已经非常丰富,所以我们此次主要针对 wls9_async_response 组件进行漏洞分析。
WebLogic Server 10.3.6.0.0
WebLogic Server 12.1.3.0.0
----------------------------------------------------------
我们可以简单请求下接口使其产生空异常,因此通过报错信息来跟踪调用过程。所示函数的调用顺序从下到上:
过反复调试,重点关注的函数如下。所列函数的调用顺序从上到下:
weblogic.wsee.server.servlet.SoapProcessor.process()
weblogic.wsee.server.servlet.SoapProcessor.handlePost()
weblogic.wsee.ws.WsSkel.invoke()
weblogic.wsee.ws.dispatch.server.ServerDispatcher.dispatch()
weblogic.wsee.handler.HandlerIterator.handleRequest()
weblogic.wsee.addressing.ServerAddressingHandler.handleRequest()
weblogic.wsee.async.AsyncResponseHandler.handleRequest()
weblogic.wsee.ws.dispatch.server.OperationLookupHandler.handleRequest()
weblogic.wsee.workarea.WorkAreaServerHandler.handleRequest()
weblogic.workarea.WorkContextMapImpl.receiveRequest()
weblogic.workarea.WorkContextLocalMap.receiveRequest()
weblogic.workarea.spi.WorkContextEntryImpl.readEntry()
weblogic.wsee.workarea.WorkContextXmlInputAdapter.readUTF()
1、 我们直接看到 SoapProcessor 的 process 函数,判断请求为 POST 后将请求内容传入 handlePost 函数处理, handlePost 函数中获取 WsPort 等内容后传入关键函数 invoke() :
2、invoke 函数中实例化 ServerDispatcher 对象后调用关键函数 dispatch() :
3、dispatch 函数中从 WsPort 中获取 InternalHandlerList 进行 setHandlerChain 操作,后再调用 getHandlerChain.handleRequest():
4、getHandlerChain 函数返回对象为 HandlerIterator ,因此进入 HandlerIterator.handleRequest() 。 handleRequest 函数根据 handlers 列表依次调用每个 handler 的 handleRequest() 。但只要某个 handler 的 handleRequest() 返回 false 则直接 return ,后面 handler 的 handleRequest() 将不再被调用。
5、 我们可以看到迭代器中的 handlers 列表,共 21 个,其中需关键控制的有 4 个。控制的重点在于:执行到 WorkAreaServerHandler.handleRequest() 之前,前面任意 handler 的 handleRequest() 均不返回 false 。
6、 首先 ServerAddressingHandler.handleRequest() 中,我们先重点关注这俩函数:
7、 其中 setWSAVersion() 中获取请求中 Message 的 ActionHeader ,根据 ActionHeader 中 namespaceURI 的不同进行不同的处理,处理结果区别在于“ weblogic.wsee.addressing.version ”属性的值是否被设置。
8、 而接下来 validateWSAVersion 函数中判断“ weblogic.wsee.addressing.version ”属性若为空,则设置为 WSAVersion.WSA10 。
9、 那么“ weblogic.wsee.addressing.version ”属性的不同会有什么影响呢?回到 handleRequest() 往下看,主要影响 var24 的值,其中等于 WSAVersion.WSA10 时 var24 为 true 。
10、 继续往下看 handleRequest() ,判断 MsgHeader 中的 ActionHeader、RelatesToHeader 存在则对相应属性进行赋值。同时使 var23、var28 为true,而 var23、var28 跟 var24 直接影响是否抛出异常,抛出异常则函数无法往下进行,本次请求中断。
11、 下面来到 AsyncResponseHandler 的 handleRequest() ,关键部分判断了 Message 的 weblogic.wsee.addressing.RelatesTo 属性值为空则返回 false 。一旦返回 false 后面的 handler 的 handleRequest() 将不再被调用。该属性在上图中进行赋值。
12、 接着来到 OperationLookupHandler 的 handleRequest() ,判断 Message 内容中是否存在 OperationName ,不存在则抛出异常,抛出异常则函数无法往下进行,本次请求中断。
13、 然后调用 WorkAreaServerHandler 的 handleRequest() ,把 Header 的 WorkAreaHeader 部分传入 WorkContextXmlInputAdapter()进行实例化 ,然后调用 receiveRequest 处理。
14、 最后执行到 WorkContextXmlInputAdapter.readUTF() 进行反序列化。
根据上述分析内容尝试构造 Poc ,暂不考虑绕过补丁部分,如何能成功执行到 WorkAreaServerHandler 漏洞触发的关键。
我们先来认识 SOAP 消息的基本结构:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
</soapenv:Body>
</soapenv:Envelope>
分析过程发现关键内容主要在 Header 部分,根据上述分析过程 7、8、9、10、11 处,我们知道 SOAP 消息的 Header 部分的 ActionHeader、RelatesToHeader 需存在,且 ActionHeader 中的 namespaceURI 需为“ http://www.w3.org/2005/08/addressing ”。
另外分析过程的 12 也说明了要求 SOAP 消息中需存在 operationName,operationName 在 AsyncResponseService.wsdl 中可查得,存在于 SOAP 消息的 Header 或 Body 均可。
最后根据分析过程 13 知 WorkAreaHeader 内容为反序列化部分。
因此 Poc 构造如下:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService">
<soapenv:Header>
<wsa:Action/>
<wsa:RelatesTo/>
<asy:onAsyncDelivery/>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
xxx
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
大致构造完成后,接下来就要考虑如何绕过 CVE-2017-10271 补丁的问题了。
首先看 CVE-2017-10271 补丁,限制了 object、new、method 元素以及 void、array 元素的属性:
但在“JavaBeans组件的长期持久性: XML 模式”文档中发现, class 元素可代替 object 元素来生成对象,且 class 元素未在补丁中限制。
由于 method 元素、 void 属性被限制,不能指定方法。但是我们可以尝试寻找可利用的构造函数,重点关注构造函数中存在可控的文件读写操作、存在使用可控内容进行反序化操作、存在可控的执命令的操作的类。
如 WebLogic10.3.6 中存在 UnitOfWorkChangeSet 类,其构造函数中使用传入的字节数组进行反序列化操作。
借助该类可成功触发 JAVA 反序列化远程命令执行漏洞。
Oracle 官方已在 2019 年 4 月 26 日发布紧急补丁,补丁显示在黑名单中添加了 class 元素。
1、 及时安装官方发布的紧急补丁。
2、 通过访问策略禁止对 /_async/* 及 /wls-wsat/* 路径的访问。
3、 若明确不使用 wls9_async_response.war与
wls-wsat.war
,建议删除并重启。
https://www.oracle.com/technetwork/security-advisory/alert-cve-2019-2725-5466295.html
https://www.oracle.com/technetwork/java/persistence3-139471.html
http://www.cnvd.org.cn/webinfo/show/4999
平安银河实验室 提醒您 : 道路千万条,谨慎第一条;渗透不规范,亲人两行泪。