In this blog post, we examine the vendor-supplied patch addressing CVE-2018-6661 . The vulnerability was initially reported to Intel Security (McAfee) in June 2017 and disclosed publicly in April 2018. Additionally, we contacted McAfee regarding the issues discussed in this post in August 2018.
Contributors: Omar El-Domeiri and Gaurav Baruah
At Exodus, we often encounter failed patches or discover adjacent zero-day vulnerabilities while conducting n-day vulnerability research. In 2018, our team has identified 24publicly disclosed vulnerabilities that were reportedly patched but, in fact, were still vulnerable because the patch did not address the root cause. Failed patches can leave users at risk even if they vigilantly keep up with software updates and security advisories.
There are many reasons why a vendor-supplied patch may fail to improve the security of the software. In some instances, a patch may actually increase the attack surface and consequently introduce new vulnerabilities. While in other instances, a patch may be incomplete, leaving avenues by which the patch can be bypassed and the vulnerable code triggered. Often incomplete patches are the result of a vendor patching specifically for the PoC they receive from disclosure without addressing the root cause. In the case of CVE-2018-6661 , we discovered an incomplete patch that left multiple ways for attackers to bypass the patch.
SummaryA publicly disclosed vulnerability for the Intel Security (McAfee) True Key software remains exploitable despite multiple vendor-supplied patches. Any logged in user, including the Guest account, can send a series of crafted requests to the True Key service to execute arbitrary code via a DLL-side loading attack vector. As a result, unprivileged users can escalate privileges to NT AUTHORITY\SYSTEM on any windows machine with True Key installed.
Background True Key is a password manager supporting several methods of sign-in including face and fingerprint, email, master password or by using a trusted device. It is freely available for Windows, Mac OS X, Android and iOS devices but requires a subscription to store more than 15 passwords. Until recently, True Key was bundled with Adobe Flash and required users to opt-out during installation.When True Key is installed on Windows it includes an always running service that listens on TCP port 30,000 on the loopback interface 127.0.0.1 which runs with SYSTEM privileges. The service coordinates functionality across various components of the True Key software by providing RPC mechanisms. In the case of this vulnerability, we are interested specifically in the SecureExecute RPC method which launches executables trusted by McAfee where trust is verified by digital signature.
Patch By examining the vendor’s patch, we can see that the patch only addresses the problem within the McAfee.TrueKey.Sync.exe and only for one of its DLL dependencies, namely theMcAfee.TrueKey.SDKLibAdapter import.When the program is run, the dot net runtime will dynamically load DLL dependencies required by the program. We can identify the direct dependencies by the imports at the top. Since Windows searches for DLLs in a specified order outlined in Microsoft’s documentation it is possible to provide a modified DLL within the same folder so that it will be imported. It should be noted that System imports are contained in the known DLLs list and can not be used in this way by an attacker.
The patch enforces that the SDKLibAdapter library must be found in the C:\Program Files\TrueKey folder (C:\Program Files\McAfee\TrueKey in more recent versions) which can not be written to by an unprivileged user. However, the binary also imports the NLog logging library and does not enforce a path constraint for the corresponding DLL. The patch is incomplete because it overlooks this and hence the nlog.dll can be utilized to allow arbitrary code execution just as the McAfee.TrueKey.SDKLibAdapter.dll could be used in versions prior to the patch. Furthermore, any other McAfee signed binary can be used to exploit the vulnerability as long as the binary depends on a DLL outside the list of known DLLs. There are multiple ways to go about finding DLL dependencies .
Reversing True KeyUpon inspection of the decompiled TrueKey service binary, it is clear that it is an Apache Thrift based service.
Thrift is a software library and set of code-generation tools developed at Facebook to expedite development and implementation of efficient and scalable backend services. Its primary goal is to enable efficient and reliable communication across programming languages by abstracting the portions of each language that tend to require the most customization into a common library that is implemented in each language. Specifically, Thrift allows developers to define datatypes and service interfaces in a single language-neutral file and generate all the necessary code to build RPC clients and servers.Examining the code auto-generated by thrift for the SecureExecute command, we can gather the data types expected for such a request to the service.
From this code, we can create our own thrift file for the subset of the RPC service that is necessary for exploitation.
The SecureExecute method takes two parameters ― a 32-bit integer clientId and a string specifying the path to an executable file to run. Before executing a RPC request, the service verifies that the clientId matches a known value that it has issued previously.
The handler for the SecureExecute API request will create a SecureExecuteCommand object, wrap it in a CheckedCommand object and pass it to the runner.Sync() method which will call the CheckedCommand object’s Execute() method.
CheckedCommand verifies that the clientId supplied in the request matches an existing ClientId that the service has already issued. If so, then it calls the Execute() method of the wrapped object which in this instance is a SecureExecuteCommand object.
SecureExecuteCommand.Execute() will inspect the requested executable to ensure that the file has been digitally signed by McAfee before spawning a child process running the executable.
So in order to get the service to actually execute a binary, we must provide it with a valid clientId and the binary must be signed by McAfee. ClientIds are issued via the RegisterClient method whose sole parameter consists of a YAPClient struct that can contain any number of optional fields. On registration, the service verifies that the client is a