CVE-2023-24583,CVE-2023-24582
Two OS command injection vulnerabilities exist in the urvpn_client cmd_name_action functionality of Milesight UR32L v32.3.0.5. A specially crafted network request can lead to arbitrary command execution. An attacker can send a network request to trigger these vulnerabilities.
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Milesight UR32L v32.3.0.5
UR32L - https://www.milesight-iot.com/cellular/router/ur32l/
8.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
CWE-77 - Improper Neutralization of Special Elements used in a Command (‘Command Injection’)
The Milesight UR32L is an industrial radio router. The router features include support for multiple VPNs, a router console shell, firewall and many others.
The router offers a service called Milesight VPN, which will connect to the Milesight VPN software. The binary client used for this service is urvpn_client
. This binary will connect to the specified Milesight VPN server but will also listen for network request to allow the sender to change VPN settings. The function that will, eventually, parse the received data and modify the VPN settings is the urvpn_client
’sexecute_urvpn_command
function:
undefined4 execute_urvpn_command(byte *data_buff)
{
[... variable declaration ...]
json = utils_parse_string2json_object(data_buff);
[... variable initialization ...]
if (json == 0) {
uVar2 = 0xffffffff;
}
else {
json_get_value_by_key(json,"type",type_value,0x40);
is_equal = strcmp(type_value,"cmd_reconnect");
if (is_equal == 0) {
sleep(5);
cmd_reconnect_action();
}
else {
is_equal = strcmp(type_value,"cmd_subnet");
if (is_equal == 0) {
[...]
}
else {
is_equal = strcmp(type_value,"cmd_name");
if (is_equal == 0) {
json_get_value_by_key(json,"name",cmd_name,0x40); [1]
cmd_name_action(cmd_name);
}
}
}
[...]
}
[...]
}
This function parses a JSON. Based on the value of the string corresponding to the key type
, the function will execute a specific command. If the type value is equal to cmd_name
, the code at [1]
will be reached and the cmd_name_action
function will be called with, as argument, the string value corresponding to the key name
in the JSON.
Following the cmd_name_action
function:
undefined4 cmd_name_action(char* cmd_name)
{
[...]
snprintf((char *)&formatted_string,0x200,
"ubus call yruo_urvpn set \'{\"base\":\"urvpn_manage\", \"value\":{\"action\":2,\"device_ name\":\"%s\"}}\'"
,cmd_name);
[...]
system((char *)&formatted_string); [2]
return 0;
}
This function uses the provided name
string value to compose a shell command that will be execute, at [2]
, through the system
function. This can lead to an OS command injection vulnerability.
There are two code paths to reach this vulnerable function, which are described as follows.
It is possible to reach the execute_urvpn_command
function through a TCP connection. The function that will manage this connection is tcp_execute_urvpn_command_wrap
:
void tcp_execute_urvpn_command_wrap(undefined4 bufev,undefined4 param_2)
{
[... variable declaration ...]
local_20 = param_2;
local_1c = bufev;
start_evbuff_ptr = bufferevent_get_input(bufev);
input_line = (byte *)0x0;
evbuffer_search_eol(ev_buffer,start_evbuff_ptr,0,&local_14,0);
if (local_14 == 0) {
[...]
}
else {
input_line = (byte *)evbuffer_readln(start_evbuff_ptr,0,0);
if (input_line != (byte *)0x0) {
log_stuff("comtcpip.c",0x4d,"_comtcpip_readcb",2,"reveive TCP :%s",input_line);
execute_urvpn_command(input_line);
[...]
}
}
[...]
} The function will receive the JSON data and eventually call the `execute_urvpn_command` with, as argument, the JSON received. No checks are performed on the received data that will eventually reach the `cmd_name_action`.
It is possible to reach the execute_urvpn_command
function through a UDP connection. The function that will manage this connection is tcp_execute_urvpn_command_wrap
:
undefined4 udp_execute_urvpn_command_wrap(int socket)
{
[... variable declaration ...]
recv_buff._0_4_ = 0;
memset(recv_buff + 4,0,0x3fc);
local_410 = 0x10;
memset(recv_buff,0,0x400);
sVar1 = recvfrom(socket,recv_buff,0x400,0,&sStack_420,&local_410);
if (sVar1 == -1) {
[...]
}
else if (sVar1 == 0) {
[...]
}
else {
log_stuff("comudp.c",0x29,"udp_read_cb",1,"Udp Read :[%s]",recv_buff);
uVar4 = execute_urvpn_command((byte *)recv_buff);
}
[...]
} The function will receive the JSON data and eventually call the `execute_urvpn_command` with, as argument, the JSON received. No checks are performed on the received data that will eventually reach the `cmd_name_action`.
Since the maintainer of this software did not release a patch during the 90 day window specified in our policy, we have now decided to release the information regarding this vulnerability, to make users of the software aware of this problem. See Cisco’s Coordinated Vulnerability Disclosure Policy for more information: https://tools.cisco.com/security/center/resources/vendor_vulnerability_policy.html
2023-02-14 - Initial Vendor Contact
2023-02-21 - Vendor Disclosure
2023-07-06 - Public Release
Discovered by Francesco Benvenuto of Cisco Talos.