Talos Vulnerability Report

TALOS-2023-1710

Milesight UR32L urvpn_client cmd_name_action OS command injection vulnerabilities

July 6, 2023
CVE Number

CVE-2023-24583,CVE-2023-24582

SUMMARY

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.

CONFIRMED VULNERABLE VERSIONS

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

PRODUCT URLS

UR32L - https://www.milesight-iot.com/cellular/router/ur32l/

CVSSv3 SCORE

8.8 - CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

CWE

CWE-77 - Improper Neutralization of Special Elements used in a Command (‘Command Injection’)

DETAILS

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.

CVE-2023-24582 - TCP handler

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`.

CVE-2023-24583 - UDP handler

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`.
VENDOR RESPONSE

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

TIMELINE

2023-02-14 - Initial Vendor Contact
2023-02-21 - Vendor Disclosure
2023-07-06 - Public Release

Credit

Discovered by Francesco Benvenuto of Cisco Talos.