Illumant has discovered a critical vulnerability in Check Point’s ZoneAlarm anti-virus software. This vulnerability allows a low-privileged user to escalate privileges to SYSTEM-level with the anti-virus software enabled. The vulnerability is due to insecure implementation of inter-process communications within the ZoneAlarm application itself, which allows a low-privilege user to inject and execute code by hijacking the insecure communications with a vulnerable .NET service. The affected .NET service is running with SYSTEM-level privileges; therefore, injected code is run at the SYSTEM-level, bypassing privilege restrictions and allowing the user to gain full control of the system.
This paper describes, at a technical level, how the exploit was discovered and how to exploit the vulnerability to attain local, unauthorized SYSTEM-level code execution.
Watch this video of the exploit in action.
Check out the exploit code on our GitHub repository.
Fabius Watson (@FabiusArtrel) recently gave a groundbreaking talk at Ekoparty 2018 on abusing WCF endpoints. Also in 2018,a number of CVEs, submitted by Watson, were released. These described privilege escalation and remote code execution vulnerabilities in various commercial products that employ .NET-based WCF services. Here are a few of them:
- CVE-2018-13101 – KioskSimpleService Local Privilege Escalation
- CVE-2018-10169 – Proton VPN Local Privilege Escalation
- CVE-2018-10170 – NordVPN Local Privilege Escalation
- CVE-2018-10190 – Private Internet Access Local Privilege Escalation
Our research is inspired by Watson’s prior work on .NET-based WCF vulnerabilities.
Techniques on code-signing flaws, published by Matt Graeber (@mattifestation) of SpecterOps, notably Code Signing Certificate Cloning Attacks and Defenses, were also applied during exploit development.
.NET Service Enumeration
A python script created by Fabius Watson can be used to help quickly identify any potentially vulnerable services that may be vulnerable. The tool enumerates all services that meet the following criteria:
- The services must be running as SYSTEM (NT AUTHORITY\SYSTEM).
- The service binary must be a .NET application.
Within the script a WMIC query is used to identify all services running as SYSTEM. Then the python module pefile is used to check if the service binary has mscoree.dll in the import table. All .NET applications depend on this library. Here’s what it looks like when run on a system with some .NET services:
With candidate services enumerated, the next thing to do is check them out in a .NET decompiler. For this purpose, we used dnSpy. Although there are many .NET services running, they may not necessarily be using WCF. All WCF services depend on System.ServiceModel, so right away we can check for a reference to this assembly in dnSpy. Only one of the ZoneAlarm services (SBACipollaSrvHost.exe) references this library:
Hunting for Exploitable Functionality
Now that a WCF service running as SYSTEM has been identified, we can check to see if it exposes methods that could be exploitable. Sometimes methods simply take a command to run as input, in which case the exploitation path is straightforward. In other cases, the exploitation vector may not be as direct. Of course, it is also possible that the service exposes no methods that can be abused for code execution.
During source code review, the OnCommandReceived method was explored. After tracing the series of calls that this method triggers, it was determined that it is used to execute an installer binary in a method down the call chain called ExecuteInstaller, which looks like this:
The name of the method, and the fact that it is used to spawn new processes, suggested that it may have potential for exploitation, which was enough for us to move on to the next step.
Interacting with the Service
Reviewing the SBACipolla class, it is apparent that two named-pipe service endpoints are created: Cipolla and CipollaRoot. WCF services can operate over a variety of transport protocols; if HTTP or TCP protocols are used, it may be possible to exploit the service remotely. In this case the service uses named-pipes, so local privilege escalation will be the goal:
The service endpoints also have a custom AddSecureWcfBehavior method called on them, an indicator that there may be some attempt by the developers to lock down these services. In fact, as we can see here, when a client attempts to connect to the named-pipe server, it first checks to see that the connection is coming from a Check Point-signed process, as shown here:
First the server determines the PID of the client. It then uses that to glean the full path to the program. Finally, it checks to see that A) the program is signed with a valid certificate and B) the CN of the certificate starts with “Check Point Software Technologies.” If these requirements are not met, the connection is killed.
Bypassing Code Signing
Our initial approach was to perform DLL injection into a legitimate Check Point-signed process to satisfy these checks and be able to talk to the service. This worked, but only when certain features of the anti-virus were disabled. In its default state, DLL injection into most processes is blocked, so this was not a promising option.
The article by Matt Graeber of SpecterOps describes a PowerShell cmdlet that makes it easy for low-privilege users to sign code with a self-signed certificate and have the OS trust the certificate. This makes it possible to sign the exploit code so that it’s possible to talk to the WCF service without injecting into another process. Signing the exploit with a fake certificate that will pass these checks can be done like this:
- $cert = New-SelfSignedCertificate -certstorelocation cert:\CurrentUser\my -dnsname checkpoint.com -Subject “CN=Check Point Software Technologies Ltd.” -Type CodeSigningCert
- Export-Certificate -Type CERT -FilePath c:\tmp\MSKernel32Root_Cloned.cer -Cert $cert
- Import-Certificate -FilePath c:\tmp\MSKernel32Root_Cloned.cer -CertStoreLocation Cert:\CurrentUser\Root\
- Set-AuthenticodeSignature -Certificate $cert -FilePath c:\tmp\exploit.exe
Developing the Exploit
An object called SBAStub is defined inside SBAStub.dll (which sits alongside the service binary in C:\Program Files (x86)\CheckPoint\Endpoint Security\TPCommon\Cipolla). This object handles all the plumbing necessary to connect to the WCF service. It also has a method called SendCommand, which we correctly guessed would interface with the OnCommandReceived method in the service. OnCommandReceived takes a string called CommandXML as an argument, which eventually gets passed on, unmodified, to ExecuteInstaller. We inspected the code in ExecuteInstaller to see how it handles that argument:
On lines 204-211 the CommandXML is deserialized into a RunInstallerPackageCommand object, which is a custom class defined in the service binary. The class has three fields, (string) InstallerPackagePath, (string) InstallerPackageArguments, and another custom class (SBAMessageInfo) MessageInfo. The most interesting field is the InstallerPackagePath because that is used to start a process in the context of the service.
On line 224 we can see there is a check to verify that the program pointed to by InstallerPackagePath is signed by Check Point.
Lines 231-232 load the arguments into a Process object, which is then started on line 235.
So it’s possible to start any Check Point-signed binary as SYSTEM.
The exploit code to make this happen looks like this:
First the SBAMessageInfo and RunInstallerPackageCommand objects are initialized. Most notably, whatever gets set in the InstallerPackagePath field is the program that the service will launch. Next, the RunInstallerPackageCommand is serialized using XmlSerializer. Finally, an SBAStub object is created and the newly serialized object is sent to the service using the SendCommand method. So long as the file in InstallerPackagePath is signed and has a CN of “Check Point Software Technologies,” it will be launched by the service.
To complete the exploit a simple program to add a new local admin to the system was created and signed again using built-in Windows PowerShell cmdlets. The service can then be instructed to launch this program to escalate privileges.
This issue was reported to Check Point as soon as a working exploit was developed. Disclosure was easy compared to many other vendors. A form is available on their website specifically for reporting security bugs. We were contacted very shortly after submission and they kept us abreast of any updates regarding the resolution status.
After the code was patched, we were asked to validate the fix. Their approach was simple and effectively made it impossible to reach the ExecuteInstaller method over WCF. Rather than try to make it difficult for unauthorized clients to interact with the service, it’s safer to simply not expose sensitive functionality over WCF.
ILLUMANT provides network- and application-level vulnerability research, penetration testing and security assessments, as well as awareness training and security compliance services to companies of all sizes and verticals, including Fortune 500 companies, universities, health care providers, government institutions, startups and many others. Leveraging strategic and tactical risk management and information security expertise, Illumant partners with its clients to help them improve security, limit exposure, and achieve compliance and training objectives. ILLUMANT is a privately held company and headquartered in Palo Alto, California.