大神们,你们投稿都是多长时间审核通过的?审核不通过,会有通知吗?
Author: 析安实验室(ZionLab)
漏洞分析
官网获取最新版本 https://ofbiz.apache.org/download.html
发现新版本对 .\framework\base\src\main\java\org\apache\ofbiz\base\util\SafeObjectInputStream.java
的 65行 进行了修改,添加了java.rmi.server
黑名单,说明此处应该存在 RMI 的利用链
寻找 SafeObjectInputStream
类的利用链
在 framework/base/src/main/java/org/apache/ofbiz/base/util/UtilObject.java
的114行
发现 SafeObjectInputStream
类被初始化使用
并且直接 return wois.readObject();
很明显是个反序列化点
继续反向跟踪 UtilObject
类getObjectException
方法的利用链
发现自身 92行 getObject()
方法调用了该方法
寻找 UtilObject.getObject()
的调用链
在 framework/entity/src/main/java/org/apache/ofbiz/entity/serialize/XmlSerializer.java
468行
deserializeCustom
方法中有调用过UtilObject.getObject()
,从名字上看是个自定义的反序列化方法
继续跟踪直到跳出本类
在94行的 deserialize
方法后没有自身调用了
继续反向跟踪调用链
framework/service/src/main/java/org/apache/ofbiz/service/engine/SoapSerializer.java:45
在 framework/webapp/src/main/java/org/apache/ofbiz/webapp/event/SOAPEventHandler.java:177
被 SOAPEventHandler
类调用,并且在前面出现了SOAPBody
等类型,说明这个类很有可能接收了request body
,后面可以验证
接着在这个方法invoke()
的最开始可以确定这个方法接收了request请求的内容
调用链梳理
request
-> SOAPEventHandler:invoke()
-> SoapSerializer:deserialize()
-> XmlSerializer:多层调用-> deserializeCustom()
-> UtilObject.getObject()-> getObjectException()
-> SafeObjectInputStream:return wois.readObject();
-> 反序列化完成
正向梳理利用链
1. 通过 SOAPEventHandler:invoke()
获取请求
可以看到获取了 wsdl
参数,这里要跳过if
判断向下执行,所以不能带上wsdl
参数
在173行
SOAPBody reqBody = reqEnv.getBody();
2. 获取到请求的 SOAPBody
内容,进入 SoapSerializer.deserialize()
3. 继续跟进 XmlSerializer.deserialize()
多次调用后来到 org.apache.ofbiz.entity.serialize.XmlSerializer#deserializeSingle
deserializeSingle
方法中开始判断xml中的标签名
这里需要将恶意代码带入到反序列化中,需要经过 value.put()
将key和value添加到map中。
4. 接着构造map,判断为map-
开头的标签应该就行
简单构造
<map-HashMap>
<map-Entry>
<map-Key>
</map-Key>
<map-Value>
</map-Value>
</map-Entry>
</map-HashMap>
接着从465行来到了468行
判断了子标签存在 cus-obj
才会进入逻辑,进入逻辑后
传入的 value
为Hex编码过的字节流
5. 接着跟进 UtilObject.getObject(valueBytes);
利用链
在 116行,恶意代码的字节流进入了存在漏洞的 SafeObjectInputStream
类
6. 跟进 SafeObjectInputStream
类
先进行了白名单的初始化,不过白名单限制不多
最后进行readObject()
进行反序列化
7. 调试 UtilObject.getObject()
的利用链是否成功
首先 利用 ysoserial 生成RMI字节流
跟推理的一样来到了 SafeObjectInputStream
类
继续调试进入 readObject()
方法反序列化
从调试参数看这里的类名为 java.rmi.server.RemoteObjectInvocationHandler
,而白名单里刚好有 java..*
,在白名单内
因此直接跳到最后 将恶意的字节流反序列化触发RCE漏洞。
漏洞复现
完整构造POC
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://ofbiz.apache.org/service/">
<soapenv:Header/>
<soapenv:Body>
<ser>
<map-Map>
<map-Entry>
<map-Key>
<cus-obj>ACED0005737D00...00000000000078</cus-obj>
</map-Key>
<map-Value>
<std-String value=""/>
</map-Value>
</map-Entry>
</map-Map>
</ser>
</soapenv:Body>
</soapenv:Envelope>