CVE-2022–24750: The Discovery and Exploitation of Zero-day Vulnerability in UltraVNC
--
Introduction
During the COVID-19 pandemic, many organizations adopted remote desktop solutions to enable employees to complete their day-to-day work from their homes. Consequently, this contributed to the massive rise in global cyber attacks as bad guys rode on the trend and hunted for software vulnerabilities in remote desktop solutions.
As a cybersecurity engineer in CSIT, my job is to build customized systems such that it meets the evolving operation requirements. It is essential that all the subsystems undergo thorough security evaluation before they are being integrated into our systems. As one of the requirements involves having remote access to our system, we have shortlisted UltraVNC, a popular open-source remote desktop solution.
Using UltraVNC as an example, I will walk you through how I used one of the simplest yet efficient techniques to discover a zero-day vulnerability (CVE-2022–24750) and exploited it to achieve local privilege escalation.
Preliminary Assessment
As vulnerability discovery is a tedious process, we will want to conduct a quick assessment of the software to narrow down the type of vulnerability to focus on.
The first thing to look at will be the privilege level of the software. For example, a software with SYSTEM privileges (in Microsoft Windows context) will be an ideal target for privilege escalation attacks. However, we also must ensure that the target software provides a means for users to interact with it. This is so that if the target software contains any vulnerability, there is a way to trigger it.
A simple task manager would suffice in telling us what kind of privilege a running software has. As shown in Figure 1, UltraVNC(winvnc.exe) is running with SYSTEM privileges.
UltraVNC also allows users to perform administrative tasks such as configuring the settings (Figure 2) through a graphical user interface (GUI). We should be able to tell from these two pieces of information whether any improper privilege management of the administrative tasks would provide an avenue for attackers to elevate their privileges.
Hunting the Vulnerability
Although UltraVNC is an open-source project, it can be a tedious task to manually hunt for vulnerabilities via source code analysis or even to develop a fuzzer to automatically find coding errors and security loopholes. For software with GUI, it will be simpler to start with exploring the functionality of the various GUI elements and observe their behaviors with tools such as Process Monitor (Procmon).
As Procmon collects lots of information, it is recommended to apply a filter so that we won’t be drowning in information. Figure 3 shows the typical set of filters I would apply when hunting for vulnerabilities related to file loading.
To prevent from drowning in information, we filter out activities that are unrelated to UltraVNC by applying the first filter (Process Name is winvnc.exe). Also, the findings from our preliminary assessment shows that UltraVNC will be an ideal target for privilege escalation. Thus, we focus on examining activities that are only executed with SYSTEM privilege by applying the second filter (Integrity is System).
I started spawning every GUI window and clicking every button on it. With every click of the button, I would observe the GUI behavior and Procmon’s output to understand what the button does. One particular button (Config) in the Admin Properties page (Figure 4) caught my attention.
Upon clicking on the Config button, an error message (Figure 5) popped up stating that the plugin cannot be loaded. Procmon also shows it is looking for a DLL file within the installed directory of UltraVNC (Figure 6).
This is an interesting lead as clicking the Config button could allow us to load a DLL with SYSTEM privilege. In addition, the input field beside the Config button seems like a place where we can manipulate the file name and file path. To verify that, I entered “abc123” into the input field with the Procmon output shown in Figure 7.
It seems like UltraVNC will try to locate and load any user specified DLL. Furthermore, we observe that there is a DLL search order pattern. We can see that this might not be ideal for an attacker as the paths above are mostly protected directories which a normal privilege user does not have write-access.
In that case, what about making it load a DLL outside of those paths? Since we have the flexibility to input any values into the field, we might be able to perform a path traversal attack. Once again, the output from Procmon shows that we are able to manipulate the path of the DLL file being loaded (Figure 8).
Exploiting the Vulnerability
To exploit the vulnerability, I built a simple DLL that spawns a command prompt upon loading. We then use the vulnerable Config button to load our malicious DLL to get a command prompt with SYSTEM privilege (Figure 9).
Vulnerable Code
As this is an open-source project, it is relatively straightforward to perform a code analysis to understand why it is possible to exploit the vulnerability in this manner.
We first identify which part of the code is responsible for the plugin loading error message. Doing a quick search of the error message shows that it can be found in winvnc\Localization.h (Figure 10).
Backtracking the code shows that the sz_ID_PLUGIN_NOT_LOAD variable (highlighted in yellow) is being referenced at line 1392 of winvnc\vncproperties.cpp (Figure 11).
Further backtracking to line 1371 (highlighted in orange in Figure 11), shows that it checks whether a plugin has been loaded. We know for sure that no plugin has been configured to load during the first installation, therefore, the code at line 1372 will execute. Tracing the reference to the LoadPlugin() function shows that it is located in DSMPlugin\DSMPlugin.cpp.
Figure 12 shows part of a code snippet in the LoadPlugin() function. We can see that line 379 performs a LoadLibrary(), a Win32 API responsible for loading DLL files. From our backtracking of codes, we can see that there are no sanity checks of the user input (szPlugin) prior to executing the LoadLibrary(),thus allowing the program to load any DLL outside of the UltraVNC installed directory.
Conclusion
In this article, we have witnessed how a simple mistake of not checking the resource path being loaded can have a consequential impact. It is important that software engineers cultivate a security-first mindset so as to avoid security vulnerabilities in their software.
Sometimes, instead of an oversight, hidden vulnerabilities can also be deliberately introduced into an innocuous software that will facilitate the attacker’s infiltration into our environment. Therefore, prior to any software deployment, organizations must conduct a thorough security evaluation to uncover potential vulnerabilities early.
This article describes a basic technique for discovering low hanging vulnerabilities. The coverage area is limited to the features made available via the graphical user-interface. To have a more comprehensive assessment, we also employ other techniques such as fuzzing and reverse engineering to discover other complex vulnerabilities such as use-after-free.
Finally, I would like to end this article by saying that cybersecurity is always a game of cat and mouse. You might have prevented the cyber threats today but you can’t be so sure that there won’t be any hidden ones that will haunt you in the future.
—
Interested to work in cybersecurity at CSIT? Check out our Careers page, we are hiring!