This is the latest in Team82's series examining the security of network management systems for the Extended Internet of Things (XIoT). Read our previous report looking into Nagios XI.
Team82 today discloses some details on five vulnerabilities in Moxa's MXview web-based network management system
MXview network management software, versions 3.x to 3.2.2 are affected
Moxa recommends users upgrade MXview to version 3.2.4 or higher to remediate these vulnerabilities
Collectively, ICS-CERT scored these vulnerabilities a 10.0, its highest criticality score. See ICS-CERT's advisory here.
An unauthenticated attacker successfully chaining two or more of these vulnerabilities could achieve remote code execution on any unpatched MXview server
Below is a demonstration of Team82's proof-of-concept exploit
Moxa's MXview is a web-based network management system designed for monitoring and managing Moxa-based devices. MXview consists of multiple components: a web server written in NodeJS, a backend process that monitors all managed computers called MXview Core, a Postgres database, and an MQTT message broker that transfers messages to and from different components in the MXview environment.
Team82's research into MXview uncovered five vulnerabilities in the MXview platform that could allow a remote, unauthenticated attacker to execute code on the hosting machine with the highest privileges available: NT AUTHORITY\SYSTEM.
As part of MXview's business logic, different processes and tasks communicate by sending and receiving messages using an MQTT broker named Mosquitto.
MQTT is a Pub/Sub (publisher/subscriber) protocol aimed at allowing remote asynchronous communication. Two entities reside in the MQTT protocol: a client that sends and receives messages, and a broker that routes messages to the appropriate clients.
In order to distribute messages to the correct clients, the broker holds a list of topics, or channels where publishers could send messages. In order for a client to receive messages, it must subscribe to a topic. Whenever a message is sent to a specific topic, the broker distributes it to all subscribed users.
Behind the scenes, the MXview software distributes most of its IPC/RPC messages through the MQTT server, and registers many callbacks to certain topics. In addition, most of the MXview APIs are using the MQTT protocol in order to receive and handle requests.
Whenever a client wants to publish a message to a certain topic, it serializes the event object using the protobuf library, which serializes data structures into binary representation. After serialization, the client publishes the new byte stream to the MQTT broker, and it distributes the message to clients that subscribe to the topic, where in turn they will convert the message to an object through the protobuf deserialization protocol.
Sensitive information, such as credentials, is sent through the MQTT channels, and many callbacks are registered to perform certain actions whenever a message is sent. Thus, accessing the MQTT will allow a malicious actor to exfiltrate sensitive data, and abuse other vulnerabilities, below to execute remote commands.
Team 82 disclosed five vulnerabilities (CVE-2021-38452, CVE-2021-38456, CVE-2021-38460, CVE-2021-38458 and CVE-2021-38454) in the MXView platform. We decided to focus on three of those vulnerabilities (CVE-2021-38452, CVE-2021-38460 and CVE-2021-38458) that could be chained to achieve pre-auth RCE on all unpatched MXView instances. All disclosed vulnerabilities were patched by Moxa last September, and users should upgrade their systems.
Team82 identified a file-read vulnerability that allows an unauthenticated attacker to read any file on the target operating system. Most of MXview's web routes require a user to be authenticated; however, this specific route does not, and we managed to identify a vulnerability allowing a malicious actor to read any file.
In most routes under the ResourceRoutes class, the sanitize-filename library is used in order to validate that the requested file does not contain malicious characters, namely path traversal characters (../).
However, in the /tmp route, the server does not use the sanitize-filename library, and instead allows the user-provided parameter as-is.
This lack of validation allows a user to supply path-traversal characters that fetch arbitrary files. Furthermore, since many passwords and configurations are saved on the disk as clear-text, a malicious user could use this unauthenticated file-read primitive to retrieve secret passwords and configurations (i.e., the password to the MQTT broker).
Team82 identified a remote code execution vulnerability, allowing any user with access to the MQTT broker (and as described above, in most cases this access is enabled by default without requiring the attacker to know a secret password) to execute arbitrary code in the highest privileges possible: NT AUTHORITY/SYSTEM.
One of the APIs accessible to any MXview user is the ping route, which is accessible through the following URL: api/sites/site/:site/ping. This API checks whether a given machine is alive by pinging it using the ICMP protocol. Whenever the user accesses this route, a request similar to the following is sent to the MXview server:
In the backend, the server validates the parameters given, and if they pass the validation check they are sent to a ping callback through the MQTT broker.
Later, an OnMessage callback is called, executing a ping cmd command using the given parameters. Because of the validation, a user could not append any malicious data to the ping command, thus preventing remote code execution through OS command injection.
It is important to note that no further validation is performed. Because validation happens before the message is published to the MQTT broker, the function trusts that the parameters it is given do not contain any malicious commands.
However, if a user could inject a MQTT message directly to the MQTT broker, the OnMessage handler will still regard the message as if it was sent by the server, thus executing ping with the given parameters. Since we can inject the message directly into the MQTT queue, no validation or sanitation will be performed on the parameters when received by the callback, thus allowing any arbitrary value to be executed.
As a proof-of-concept, we've built the following MQTT message, and assigned an IP parameter containing our OS command injection payload, thus achieving remote command execution.
This vulnerability allows an unauthenticated user to write arbitrary files on the host server's file system.
A MXview feature allows users to add custom icons. An administrator does so by accessing a route that uploads a PNG file to the web server and points to the new icon file.
In order to restrict users from uploading files to any directory under any name, the server chooses the icon filename and instead saves only the file extension from the user-given file. The server then takes the user's request, serializes it, and sends it to the MQTT broker, creating an action that will change a site's icon.
After the message is received, the onMessage callback is called with the created event, which results in the creation of the icon file.
An attacker could abuse this by sending a malicious MQTT message containing path traversal characters, and inject it directly into the MQTT topic, thus resulting in the creation of arbitrary files on the host server's file system.
Our PoC combines several vulnerabilities, resulting in unauthenticated remote code execution. Here is an example of how we chained a couple of the vulnerabilities above to achieve pre-auth remote code execution with SYSTEM privileges:
In order to execute code with high privileges, we first need to have access to the MQTT message queue and inject our crafted message. To do so, we need to get the MQTT password. We can do this by exploiting CVE-2021-38452 and read the configuration file gateway-upper.ini which includes the MQTT password as plain-text.
After grabbing the MQTT password, we can use CVE-2021-38454 to inject a crafted MQTT message to the Ping route callback. This malicious message will trigger a command injection vulnerability and execute our code with SYSTEM privileges.