Triskele Labs
During a recent engagement, we encountered a fairly bare and feature-free Standard Operating Environment (SOE). The up-to-date Windows installation only had two non-standard software packages installed, one of which was RealVNC Server 6.8.0. The main objective was to escalate our privileges on this system and in this article we will describe a quick but effective privilege escalation bug we discovered in RealVNC Server 6.8.0. RealVNC allows users to install the server component either via .exe or Microsoft Installer (.msi). In this case this was deployed via the .msi. Some vendors opt to allow regular users to initiate a repair of this software, which is supported by the Microsoft Installer software. This can be performed by either going into the Programs & Features menu and selecting ‘Modify’, or by kicking off the repair via the command line:
msiexec /fa “{ProductID}”
The ProductID can be found via PowerShell using the following one-liner:
get-wmiobject Win32_Product | Sort-Object -Property Name |Format-Table IdentifyingNumber, Name, LocalPackage -AutoSize
Initiating a repair via msiexec.exe is an interesting attack vector, as it involves the elevated msiexec service and it can often be invoked by regular users. This doesn’t mean that every repair is vulnerable, and it still depends on whether the repair option performs any privileged file operations on user-writable or user-controllable locations.
After initiating a repair of RealVNC Server, the elevated msiexec.exe
service starts creating files in %TEMP%
. However, it is not creating these files in the SYSTEM %TEMP%
directory, which is C:\Windows\Temp
, but in the %TEMP%
directory of the user initiating the repair, which is C:\users\<username>\appdata\local\temp
.
In ProcMon, we can see that one of the files being created, without impersonating the current user, is vncserver-old.exe
:
Once vncserver-old.exe
is written, it is also launched with SYSTEM privileges without impersonating the user:
As shown in these screenshots, since it is being run from a fairly bare directory, it attempts to load a few shared libraries which aren’t present (activeds.dll
, adsldpc.dll
), thus opening an opportunity for DLL hijacking the vncserver-old.exe
process and gaining command execution as SYSTEM.
One easy and straightforward way to do this would be to use FuzzySec’s Get-Exports PowerShell script (https://github.com/FuzzySecurity/PowerShell-Suite/blob/master/Get-Exports.ps1) and clone the exports of adsldpc.dll
, forwarding them to the original adsldpc.dll
in C:\Windows\System32\adsldpc.dll
.
We can add the output of Get-Exports
to our DLL code in Visual Studio and execute a simple command to test our theory.
We’ll compile this for 64-bit (or 32-bit depending on your RealVNC architecture), copy the adsldpc.dll
to %TEMP%
, fire up ProcMon again and initiate a repair once more.
It looks like the C:\output.txt
file was successfully created and shows that we’re running with elevated privileges.
From here, it’s just a matter to weaponise the vulnerability in a way that fits the engagement - you could load a beacon into memory via memory injection, or simply add yourself to the Local Administrators group.
We found that versions 5.2.3 up until and including 6.8.0 of RealVNC Server installed via .msi were vulnerable to this attack but no prior versions were tested. Of note is that version 5.2.3 attempted to load different DLLs from this %TEMP%
directory, so instead of adsldpc.dll
we hijacked version.dll
to achieve the same result for this version.
Timeline
07 March 2022 - Vulnerability reported to RealVNC 07 March 2022 - Report acknowledged 10 March 2022 - Confirmation they are able to reproduce and are working on a fixed version 22 March 2022 - CVE-2022-27502 assigned, RealVNC indicates a fix will be out soon 07 April 2022 - RealVNC Server 6.9.1 released to address the issue 14 April 2022 - Coordinated disclosure