CVE-2024-28027,CVE-2024-28025,CVE-2024-28026
Three OS command injection vulnerabilities exist in the web interface I/O configuration functionality of MC Technologies MC LR Router 2.10.5. A specially crafted HTTP request can lead to arbitrary command execution. An attacker can make an authenticated HTTP 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.
MC Technologies MC LR Router 2.10.5 (QEMU)
MC LR Router - https://mc-technologies.com/en/produkt/100800/
7.2 - CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
CWE-78 - Improper Neutralization of Special Elements used in an OS Command (‘OS Command Injection’)
The MC LR Router from MC Technologies comes in two-port and four-port variants, as well as models that support transparent serial-to-TCP translations and 1-in/1-out digital I/O. The router boasts support for IPsec and and OpenVPN VPN implementations, firewall capabilities, remote management via HTTP and SNMP, and configurable alerting via SMS and email.
The MC-LR Industrial Router from MC Technologies comes in two-port and four-port variants, as well as models that support transparent serial-to-TCP translations and 1-in/1-out digital I/O. The router boasts support for IPsec and and OpenVPN VPN implementations, firewall capabilities, remote management via HTTP and SNMP, and configurable alerting via SMS and email.
The MC LR router can be configured via a locally-hosted HTTP interface. The HTTP server in use is busybox’s httpd, hosting a variety of cgi-bin files written in C. There are three authenticated OS command injection vulnerabilities in the cgi-bin file responsible for handling configuration and control of the various I/O on the device. User input provided via three distinct HTTP parameters can be injected directly into OS commands that are called with root privileges via calls to system
.
The vulnerable file is located at /wbm/cgi-bin/p/adm/io
and is accessible via HTTP at the URI /cgi-bin/p/adm/io
. The vulnerable function, which we refer to as form_handler
, begins at offset 0x8cec
. This function is responsible for handling HTTP requests made to the io
endpoint. A partial, annotated decompilation is included below for reference.
int form_handler(
struct cgi* cgi,
struct param* params,
int num_params,
REQUEST_TYPE req_type,
) {
if (num_params > 0)
{
param_t* current_param = params;
int num_parsed_params = 0;
// [1] For each HTTP parameter ...
do
{
if (req_type == GET)
{
int io_idx = -1;
char** command;
int command_status = 0;
// [2] Craft unique commands based on whether the parameter was titled `btn`, `out`, or `timer`
...
It is at this point in the function where the first of the three vulnerabilities arise. This section of the function acts almost like a switch-case over the possible parameters (btn1
, out1
, timer1
), using each to construct a slightly different OS command and execute it.
btn1
parameterint btn_ret = sscanf(current_param->key, "btn%u", &io_idx);
if (btn_ret == 1 && io_idx == 1)
{
// [3] If the key was `btn1` then inject the attacker-controlled value into the command and execute it
if (asprintf(&command, "/usr/sbin/vout %s %u vo_manual", current_param->value, 1) > 0)
{
system(command);
return -1;
}
}
Note that if the current parameter is btn1
then both btn_ret
and io_idx
will be 1
, satisfying the conditional. Inside the conditional, an OS command is constructed using the provided value of the parameter and the command is executed.
out1
parameterint out_ret = sscanf(current_param->key, "out%u", &io_idx);
if (out_ret == 1 && io_idx == 1)
{
// [4] Similar to `3`, but `out1` instead of `btn1`
if (asprintf(&command, "/usr/sbin/vout %s %u vo_manual", current_param->value, 1) > 0)
{
system(command);
return -1;
}
}
Note that if the current parameter is out1
then both out_ret
and io_idx
will be 1
, satisfying the conditional. Inside the conditional, an OS command is constructed using the provided value of the parameter and the command is executed.
timer1
parameterint timer_ret = sscanf(current_param->key, "timer%u", &io_idx);
if (timer_ret == 1 && io_idx == 1)
{
// [5] Similar to `[3]` and `[4]`, but `timer1` instead of `btn1` or `out1`
if (asprintf(&command, "/usr/sbin/vout oneshot %u %s", 1, current_param->value) > 0)
{
system(command);
return -1;
}
}
Note that if the current parameter is timer1
then both timer_ret
and io_idx
will be 1
, satisfying the conditional. Inside the conditional, an OS command is constructed using the provided value of the parameter and the command is executed.
It is important for us to state that in the above decompilations we excluded a significant amount of HTML generation that, for the purposes of this report, only increased clutter and difficulty in understanding the vulnerable code. As indicated previously, there are three distinct parameters that can cause unique command injections - btn1
, out1
and timer1
. Respectively, the vulnerable calls to system
are crafted at [3]
, [4]
, and [5]
with very little differentiation. The attacker controlled value of those parameters is injected directly into the shell command without sanitization, and will be executed with root privileges.
2024-03-07 - Initial Vendor Contact
2024-03-12 - Vendor Disclosure
2024-04-02 - Request confirmation of receipt
2024-05-15 - Announcement of upcoming 90 day period expiration sent to vendor
2024-06-04 - Phone call to vendor. Vendor Disclosure sent to different recipient.
2024-06-24 - Email from vendor. Content unclear. Matter potentially resolved.
2024-07-02 - Status request sent to vendor
2024-08-21 - Announcement of upcoming 90 day period expiration sent to vendor
2024-09-03 - Upcoming release announcement
2024-11-21 - Public Release
Discovered by Matt Wiseman of Cisco Talos.