Apache OFBiz RMI反序列化远程代码执行漏洞(CVE-2021-26295)
字数 1938 2025-08-05 13:25:32
Apache OFBiz RMI反序列化远程代码执行漏洞(CVE-2021-26295)分析报告
漏洞概述
Apache OFBiz是一个开源的企业资源规划(ERP)系统,在其SOAP服务处理过程中存在一个RMI反序列化远程代码执行漏洞(CVE-2021-26295)。攻击者可以通过构造恶意的SOAP请求,利用不安全的反序列化操作实现远程代码执行。
漏洞分析
漏洞根源
漏洞根源在于SafeObjectInputStream类的反序列化操作中,虽然设置了白名单但限制不严格,特别是对java.rmi.server包下的类没有进行有效限制。
漏洞利用链分析
完整的漏洞利用调用链如下:
request -> SOAPEventHandler:invoke() -> SoapSerializer:deserialize() -> XmlSerializer:多层调用-> deserializeCustom() -> UtilObject.getObject()-> getObjectException() -> SafeObjectInputStream:return wois.readObject(); -> 反序列化完成
详细调用过程
-
SOAP请求入口点
SOAPEventHandler.invoke()方法接收SOAP请求- 获取请求的SOAPBody内容:
SOAPBody reqBody = reqEnv.getBody(); - 注意:请求中不能包含
wsdl参数,否则会跳过漏洞触发路径
-
序列化处理
- 进入
SoapSerializer.deserialize()方法 - 进一步调用
XmlSerializer.deserialize()方法
- 进入
-
XML反序列化
- 进入
XmlSerializer.deserializeSingle()方法 - 解析XML标签,需要构造特定格式的恶意XML:
<map-HashMap> <map-Entry> <map-Key> <cus-obj>恶意序列化数据</cus-obj> </map-Key> <map-Value> <std-String value=""/> </map-Value> </map-Entry> </map-HashMap> - 关键点:必须包含
cus-obj标签才能进入漏洞触发路径
- 进入
-
反序列化执行
- 通过
UtilObject.getObject()方法处理恶意数据 - 最终调用
SafeObjectInputStream.readObject()执行反序列化
- 通过
漏洞触发条件
- 请求必须为有效的SOAP请求
- 请求体必须包含特定结构的XML,其中
cus-obj标签内包含恶意序列化数据 - 不能包含
wsdl参数
漏洞复现
POC构造
完整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>
其中cus-obj标签内容为使用ysoserial生成的RMI恶意序列化数据(Hex编码)。
复现步骤
- 使用ysoserial生成RMI恶意序列化字节流
- 将字节流转换为Hex编码
- 构造上述POC,将Hex编码数据放入
cus-obj标签 - 向目标OFBiz系统发送该SOAP请求
- 观察RCE是否执行成功
修复方案
官方修复方案:
- 在
SafeObjectInputStream.java的65行添加了java.rmi.server包到黑名单 - 建议升级到最新版本OFBiz
临时缓解措施:
- 禁用不必要的SOAP服务
- 在网络边界过滤包含可疑序列化数据的SOAP请求
技术细节
关键类分析
-
SafeObjectInputStream
- 位于
framework/base/src/main/java/org/apache/ofbiz/base/util/SafeObjectInputStream.java - 负责反序列化操作,但白名单限制不足
- 位于
-
UtilObject
- 位于
framework/base/src/main/java/org/apache/ofbiz/base/util/UtilObject.java - 提供对象序列化/反序列化工具方法
- 关键方法:
getObject()和getObjectException()
- 位于
-
XmlSerializer
- 位于
framework/entity/src/main/java/org/apache/ofbiz/entity/serialize/XmlSerializer.java - 包含
deserializeCustom()方法,处理自定义反序列化
- 位于
-
SoapSerializer
- 位于
framework/service/src/main/java/org/apache/ofbiz/service/engine/SoapSerializer.java - SOAP消息的反序列化入口
- 位于
调试技巧
-
关键断点设置:
SOAPEventHandler.invoke()XmlSerializer.deserializeCustom()UtilObject.getObject()SafeObjectInputStream.readObject()
-
调试时可观察
java.rmi.server.RemoteObjectInvocationHandler类是否被成功反序列化
总结
该漏洞通过精心构造的SOAP请求,利用OFBiz中不安全的反序列化操作实现RCE。漏洞利用链较长但逻辑清晰,关键在于理解XML到对象的反序列化过程以及OFBiz对SOAP请求的处理机制。修复方案应重点关注反序列化操作的白名单/黑名单机制。