TL;DR: CVE details for a COM-based local privilege elevation with a brief write-up on discovery to root.
Download exploit code here.
The CxUtilSvc system service (CxUtilSvc.exe) is associated with the Synaptics Sound Device Driver. The service exposes a COM interface named
IRegistryHelper that is used by the end-user GUI to update certain software settings in the registry. However, the scope was not limited to the appropriate key in the HKLM hive and this allowed for arbitrary registry access. A malicious program running in a low-privileged context could then leverage this to elevate its privileges on the system, as shown below. Vulnerable versions of this service (i.e. prior to v188.8.131.52) were found on various OEM units including Lenovo, HP, ASUS, and LG.
The suggested remediation was straightforward. The read and write functions would be constrained such that they would only be accessible to the domain of
HKLM\Software\Conexant and to reject reading and writing to any other places.
Obligatory proof-of-concept video:
2018-12-26: Discovered vulnerability and developed baseline proof-of-concept.
2018-12-27: Refactored exploit for robustness, readability, and compatibility.
2018-12-27: Sent vulnerability report and exploit to Lenovo PSIRT.
2019-01-17: Synaptics team sent a detailed proposal of remediation options.
2019-03-21: Extended the disclosure deadline after receiving more context.
2018-04-08: Received confirmation of disclosure date and CVE identifier.
2019-04-15: Coordinated disclosure date for this vulnerability.
The teams at Lenovo and Synaptics were responsive and cooperative. After the holidays, Synaptics had a quick turnaround in proposing and implementing a fix. Although the rollout of the remediation took a little longer, this was expected with all the coordination involved between Synaptics, OEMs, and Microsoft. I would work with them again should the opportunity arise.
The remainder of this post is a brief write-up that goes over how the vulnerability was found and the exploit development process. The vulnerability itself is relatively simple, so this could serve as a gentle and narrow introduction to exploiting COM objects.
Finding vulnerabilities in an OEM or enterprise master image can be useful from an offensive perspective because of the potential blast radius that comes with a wide deployment. The goals can typically involve finding a combination of remote code execution (RCE), local privilege elevation (LPE), and sensitive data exposure. Check out my previous post for a methodology intro.
When it comes to software bugs that lead to LPE, you can look for customizations introduced into the master image such as system services and kernel-mode drivers which run in a privileged context and may not receive as much scrutiny. For this vulnerability, I was looking for system services hosting COM interfaces that low-privileged code can communicate with.
I'm nowhere near an expert at COM, but it makes sense to briefly explain what that is before going further. COM is Component Object Model, which is one of Microsoft's ways to have reusable code that is distributed and agnostic of platform and language. This allows you to get communication between processes and systems (IPC) using a variety of languages. Note that a set of functions in a COM object is called an interface, and the functions within an interface are called methods.
To start enumerating COM interfaces, I used James Forshaw's useful OleViewDotNet tool. As I was looking for system services that were hosting COM interfaces, I thought it would be natural to look under Registry → Local Services. Perhaps I misunderstood, but I did not end up finding the vulnerable
IRegistryHelper interface that way. Instead, I found it by going to Processes → All Processes → By User and then trawling through processes that were running as SYSTEM.
Luckily, a type library was available for this interface which gives us information about structures and methods as you can see below. This helps us get more semantic context faster. If this wasn't here, we can still analyze the binary with Ghidra/IDA/etc.; it's just more leg work.
Considering that the code is hosted in the high-privileged CxUtilSvc.exe process, the methods that interact with the registry are interesting, particularly if we can modify the
HKEY_LOCAL_MACHINE (HKLM) hive which is typically reserved for high-privileged users (e.g. administrators). With that, we can start looking into ways to elevate privileges by modifying the registry. But what should we modify and how do we invoke these methods to start?
To invoke these methods, we can start by launching Visual Studio and creating a .NET console app. In the Solution Explorer, we can add a reference to the
CxUtilSvcLib type library. This will allow us to easily use those methods in the
The next step would be to write the exploit primitives. As with my last exploitation post, I recommend writing exploits in a modular way so that the code can be re-used more easily. Here, it's fairly straightforward because we have the type library. After adding the reference, we can use methods from the
RegistryHelper class in the
CxUtilSvcLib namespace to implement our primitives.
From here we can implement other functions that use the primitives to elevate privileges. But how can we modify the registry to gain LPE? For PoC purposes, I used a simpler and not-so-stealthy technique which does the following:
- Modify the path of an existing service to a command that elevates the current user.
- Start the service (only a few can be started and stopped as a Standard user).
- Replace the service path back to the original one.
You can read the exploit code here. If all compiles as expected, you should see the exploit work like below.
Thank you for taking the time to read this! Please ping me if you have any feedback, questions, or complaints.