Talos Vulnerability Report

TALOS-2023-1706

Milesight UR32L vtysh_ubus toolsh_excute.constprop.1 OS command injection vulnerabilities

July 6, 2023
CVE Number

CVE-2023-24519,CVE-2023-24520

SUMMARY

Two OS command injection vulnerability exist in the vtysh_ubus toolsh_excute.constprop.1 functionality of Milesight UR32L v32.3.0.5. A specially-crafted network request can lead to 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:L/UI:N/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 cellular router. The router features include support for multiple VPNs, a router console shell, firewall and many others.

The Milesight router offers several functionalities through the /cgi endpoint. The “core” functionality we are considering is called yruo_tools, in this “core” there are two functions: “ping” and “traceroute”. For instance, the payload for the /cgi API to use the “traceroute” functionality is would look likes this:

{
    "id": 60,
    "execute": 1,
    "core": "yruo_tools",
    "function": "traceroute",
    "values": [
        {
            "host": "<some_host>"
        }
    ]
} The ping one would differ for the `"function"` value that would be "ping". 

Both “ping” and “traceroute” will end up calling the vtysh_ubus’s toolsh_excute.constprop.1 function.

void toolsh_excute.constprop.1(void *ping_or_trace,undefined4 params,void *rcp_session)

{
  [... variable declaration ...]

  [... variable initialization ...]
  [...]
  get_tool_path.constprop.4(ping_or_trace,1,rcp_session,(char)lock_path);
  get_tool_path.constprop.4(ping_or_trace,0,rcp_session,(char)log_path);
  if (ping_or_trace == (void *)0x0) {
    command = "ping";
  }
  else {
    command = "trace";
  }
  snprintf(shell_cmd,0x120,"%s %s %s %s %s &","/usr/sbin/webtools.sh",command,params,log_path,
           lock_path);                                                                                  [1]
  printf("** lock=%s **\n** path=%s **\n** command=%s **\n",lock_path,log_path,shell_cmd);
  does_lock_exist = access((char *)lock_path,0);
  if (does_lock_exist == 0) {
    [..]
  }
  else {
    lock_fd = open((char *)lock_path,0x41,0);
    if (-1 < lock_fd) {
      close(lock_fd);
      system(shell_cmd);                                                                                [2]
      [...]
    }
    [...]
  }
  [...]
} This function based on the `ping_or_trace` parameters will compose, at `[1]`, the string `/usr/sbin/webtools.sh <ping/trace> <params> <log_path> <lock_path> &`. If another "ping" or "traceroute" command is not currently running, checked with the lock file, the composed string will reach the `system` function at `[2]`. Because the `params` parameters is not checked or parsed enough, this can lead to an OS command injection at `[2]`. Following the "ping" and "traceroute" related function that will call the vulnerable `toolsh_excute.constprop.1` function.

CVE-2023-24519 - tools_ping

The tools_ping is the function responsible for managing the ping function in the yruo_tools “core”:

void tools_ping(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,
               undefined4 *data)

{
  [... variable declaration ...]
  
  [... variable initialization ...]
  json_msg_output("!! yruo_tools.ping params",data);
  blob_buf_init(b,0);
  len = __bswapsi2(*data);
  blobmsg_parse(tools_ping_policy,2,tb,data + 1,(len & 0xffffff) - 4);
  if ((tb[0] == (blob_attr *)0x0) || (tb[1] == (blob_attr *)0x0)) {
    blobmsg_add_string(b,"error","lack of param to test");
  }
  else {
    blob_string = (char *)blobmsg_get_string((char *)tb[0]);
    strncpy(ping_host,blob_string,0x40);                                                                [3]
    blob_string = (char *)blobmsg_get_string((char *)tb[1]);
    strncpy(ubus_rpc_session,blob_string,0x40);
    strtok(ping_host," ");                                                                              [4]
    toolsh_excute.constprop.1(0,ping_host,ubus_rpc_session);
  }
  [...]
}

The data are transmitted through blobmsg structures, the two variable that eventually will reach this function transmitted are: - host: a parameter that should represent the host that will be pinged - ubus_rpc_session: a parameter that will be used to check if the provided request was performed by someone that had logged in successfully

At [3] the host parameter is copied and then, at [4], only the first word, separated by a space, is taken into consideration. This first word will became the params parameter for the toolsh_excute.constprop.1. Here the only parsing performed on the host parameter is considering only the first word before a space. This is not enough to prevent an OS command injection vulnerability

CVE-2023-24520 - tools_trace

The tools_trace is the function responsible for managing the “traceroute” function in the yruo_tools “core”:

void tools_trace(undefined4 param_1,undefined4 param_2,undefined4 param_3,undefined4 param_4,
                undefined4 *data)

{
  [... variable declaration ...]
  
  [... variable initialization ...]
  json_msg_output("!! yruo_tools.traceroute params",data);
  blob_buf_init(b,0);
  len = __bswapsi2(*data);
  blobmsg_parse(tools_trace_policy,2,tb,data + 1,(len & 0xffffff) - 4);
  if ((tb[0] == (blob_attr *)0x0) || (tb[1] == (blob_attr *)0x0)) {
    blobmsg_add_string(b,"error","lack of param to test");
  }
  else {
    tmp = (char *)blobmsg_get_string((char *)tb[0]);
    strncpy(host,tmp,0x40);                                                                             [5]
    tmp = (char *)blobmsg_get_string((char *)tb[1]);
    strncpy(ubus_rcp_session,tmp,0x40);
    strtok(host," ");                                                                                   [6]
    toolsh_excute.constprop.1(1,host,ubus_rcp_session);
  }
  [...]
}

The data are transmitted through blobmsg structures, the two variable that eventually will reach this function transmitted are: - host: a parameter that should represent the host that will used for the “traceroute” functionality - ubus_rpc_session: a parameter that will be used to check if the provided request was performed by someone that had logged in successfully

At [5] the host parameter is copied and then, at [6], only the first word, separated by a space, is taken into consideration. This first word will became the params parameter for the toolsh_excute.constprop.1. Here the only parsing performed on the host parameter is considering only the first word before a space. This is not enough to prevent an OS command injection vulnerability

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.