CVE-2023-24519,CVE-2023-24520
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.
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:L/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 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.
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
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
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.