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
Team82’s proof-of-concept executing code on an MXview server.
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.
The architecture of the MXview platform.
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.
A message sent through the MQTT broker, containing a username and password.
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.
CWE-22: Unauthenticated File Read through Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)
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 (../).
A route inside the ResourceRoutes class, which uses the sanitize function in order to validate the user-requested file.
However, in the /tmp route, the server does not use the sanitize-filename library, and instead allows the user-provided parameter as-is.
The /tmp route, allowing the user-given filename without using the sanitize-filename library.
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).
An attack abusing this vulnerability, reading the gateway-upper.ini file inside the MXview-gateway/config directory. All slashes are urlencoded (%2f), thus resulting in the fetching of (../../../MXview-gateway/config/gateway-upper.ini file).
Injecting MQTT Messages
CVE-2021-38454 and CVE-2021-38458
CWE-78: Remote Code Execution through Improper Neutralization of Special Elements used in an OS Command (OS Command Injection)
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:
A ping request sent to an 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.
Validation on the server side of the parameters given to the ping request.
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.
The ping function, taking the parameters it is given (from the MQTT Message), and executing as a part of a cmd command.
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.
The malicious MQTT payload which creates a ping action, contains a malicious OS command injection inside the IP parameter. When the server receives this message, it executes malicious code (in this case, the execution of the whoami command and the redirection of the output to c:\\claroty.poc).
This diagram represents an exploit flow. An attacker injects malicious messages to the MQTT broker directly, bypassing all input validation performed by the server, and achieves arbitrary remote code execution through the OS command injection vulnerability.
CWE-22: RCE Through Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)
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.
The saveSiteIcon function receives the icon data and extension from the MQTT broker, and creates a file in the resources/icons/sites directory.
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.
A malicious MQTT message, containing path traversal characters inside the ext parameter Whenever the server executes the onMessage callback, a file will be created named claroty_poc.
Proof of Concept
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:
CVE-2021-38452 (get credentials) → CVE-2021-38454 (Injecting specifically crafted MQTT message to the Ping route callback) → Remote code execution with SYSTEM privileges through OS command injection.
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.
Abusing CVE-2021-38452: grabbing the gateway-upper.ini configuration file containing the MQTT password.
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.