Pulse Secure Client for Windows <9.1.6 TOCTOU Privilege Escalation (CVE-2020-13162)

In the midst of the coronavirus pandemic we have observed an incredible boost in the diffusion of configurations allowing people to work from home. Being able to quickly identify vulnerabilities in the components of these infrastructures has become, more than before, a priority for many businesses. So the lenient Red Timmy has thought: “it would be good to kill some 0day while we go through this hard time“.

After careful evaluation of the options available, we have decided to proceed with a deep inspection of the Pulse Secure VPN client. Why? Beyond the large installation base in the Fortune 500 market, there are plenty of medium-size companies out there adopting the Pulse Secure products. Try to imagine a business distributing laptops to its employees through which they can connect remotely, via VPN, to the employer’s infrastructure and comfortably work from home. Of course the operating system running on these laptops is hardened in order to disallow the installation of arbitrary software, disable the antivirus or the other monitoring/security agents and more in general to avoid the execution from employees of any actions that would normally require admin rights.

Now imagine an employee (might be a malicious insider) escalating to “NT_AUTHORITY\SYSTEM” in one of these laptops before or after having established a connection to the company VPN network, with security measures, configurations and software disabled or tampered, with the possibility to install any programs or hide hacking tools in the system without restrictions, with the aim to lower down the threat detection and identification capabilities of SOC. How bad would it be? This is what could have happened by exploiting the vulnerability on Pulse Secure client we are going to talk about today, before the vendor patched it. We have registered CVE-2020-13162 for that.

High-Level Overview and Impact

Pulse Secure Client for Windows suffers of a local privilege escalation vulnerability in the “PulseSecureService.exe” service. Exploiting this issue allows an attacker to trick “PulseSecureService.exe” into running an arbitrary Microsoft Installer executable (“.msi”) with SYSTEM privileges, granting them administrative rights.

The vulnerability lies in the “dsInstallerService” component, which provides non-administrative users the ability to install or update new components using installers provided by Pulse Secure. While “dsInstallerService” performs a signature verification on the content of the installer, it has been found that it’s possible to bypass the check providing the service with a legit Pulse Secure installer and swapping it with a malicious one after the verification (see Analysis paragraph below).

The vulnerability is a TOCTOU (time-of-check to time-of-use) and can be exploited reliably using an exclusive opportunistic lock.

This bug can be exploited in default configuration and the tester is not aware of any available configuration preventing exploitation. All the versions we have tested < 9.1R6 (including the branch 5.x as the version 5.3 R70 released on January 2017) have been successfully exploited during our tests. The checks were conducted both on a fresh install of Windows 10 1909 and Windows 8.1.

The bug was discovered by Giuseppe Calì (@gsepcali). A full exploit, which will be released in the near future, has been written by Marco Ortisi (more about the exploit in the notes below).


The server component of the Pulse Secure solution, Pulse Secure Connect, provides installers to deploy on client machines. Some of these, such as “Pulse Secure Installer Service (.exe)” and “Host Checker (.exe)“, can be installed without admin privileges (see Figure 1).

Figure 1: description of one of the observed installers provided in the PSC admin interface.

Despite stating that the packages “can be deployed with limited user privileges if a previous version of the Installer Service is running“, it has been found that a default install of Pulse Secure client allows to run the installers. The installers are available at “https://<pcs-host>/dana-admin/sysinfo/installers.cgi “.

Since these installers need to perform tasks requiring administrative right (such as creating files into the “Program Files (x86)” directory), we have decided to investigate how the corresponding non privileged processes are allowed to perform privileged tasks.

The installers are self-extracting executables (see Figure 2).

Figure 2: the extracted content of the “Pulse Secure Installer Service (.exe)” package.

Pulse Secure Installer Service (.exe)” works in the following way:

  1. Extracts its content to %TEMP%.
  1. Instructs “PulseSecureService.exe“, which runs as SYSTEM, to initiate the install process. This is done via a OLE interface exposed by the service.
  1. PulseSecureService.exe” verifies the signature of “VerifyAndInstall.exe” using the “CryptQueryObject()” WinAPI function.
  1. If the signature is valid, “PulseSecureService.exe” copies “VerifyAndInstall.exe” to “C:\Windows\Temp\PulseXXXXXXXX\“, where “XXXXXXXX” is a hex-encoded timestamp.
  1. PulseSecureService.exe” runs “VerifyAndInstall.exe“.
  1. VerifyAndInstall.exe” runs a verification routine on “%TEMP%\PulseSecureInstallerService.msi
  1. If the verification succeds, “PulseSecureInstallerService.msi” is copied to “C:\ProgramData\Pulse Secure\Installers\verified_PulseSecureInstallerService.msi“.
  2. PulseSecureInstallerService.msi” runs “C:\Windows\system32\msiexec.exe” as SYSTEM with “C:\ProgramData\Pulse Secure\Installers\verified_PulseSecureInstallerService.msi” as an argument and the installation starts.

The installation process can be observed using “Procmon” with the file names above as filters.

C:\ProgramData” is writable by non privileged users, that can create or modify files they own but not those created by other users.

In order to reproduce the issue and run code as SYSTEM, it is necessary to:

  1. Create an empty “C:\ProgramData\Pulse Secure\Installers\verified_PulseSecureInstallerService.msi
  1. Set an exclusive opportunistic lock on “C:\Windows\System32\msiexec.exe” (for example using this tool: https://github.com/googleprojectzero/symboliclink-testing-tools/tree/master/SetOpLock with the command “SetOpLock.exe C:\Windows\System32\msiexec.exe x“).
  1. Start the legit installer downloaded from the “Pulse Secure Connect” appliance.
  1. When the oplock is triggered, swap “C:\ProgramData\Pulse Secure\Installers\verified_PulseSecureInstallerService.msi” with a malicious “.msi” file.
  1. Release the oplock.

As a result, the malicious “.msi” file is executed with SYSTEM privileges.

Detection guidance

In order to detect this issue, it is sufficient to look for a non-SYSTEM process creating or writing to “C:\ProgramData\Pulse Secure\Installers\“. As the original files are always created and written to by the PulseSecure service, non-privileged writes to this location are always non-standard behavior and a possible exploitation attempt.

Different installers install to different locations. Another file path to watch for non privileged writes is “C:\ Users\<user>\AppData\Roaming\Pulse Secure“.


We have developed two different exploits for this vulnerability. See one of them in action below.

However, we are not going to release the code immediately, but it will be published in our github soon. Why not now? Well, we have realized that is very difficult in practice, for Pulse Secure customers, to understand when the release of a new version of the VPN client provides a security bug fix or just a feature update. In fact, in the moment we write, both the release notes of the VPN client version 9.1R6 (the only one not affected) and the Security Advisories published in the PulseSecure website contain no mention to the fact that the previous versions of the product were affected by CVE-2020-13162.

The natural consequence of this reasoning is that there are very high chances that nobody has really updated the client with the latest version available because nobody is really aware of the fact that it provides a bug fix and not a feature update.

Update: 24 hours after we disclosed this vulnerability, Pulse Secure has released a security advisory related to it.

That’s all for today. Remember to follow us on twitter and while you are there connect to @gsepcali. More vulnerabilities and Red Team stories are coming…stay tuned!

Disclosure timeline

Vulnerability discovered: April 13th, 2020
Vendor contacted: April 15th, 2020
Vendor’s reply: April 17th, 2020
Patch released: May 22nd, 2020
Red Timmy Disclosure: June 16th, 2020
Security Advisory released by Pulse Secure: June 17th, 2020

Exploit release: date to be confirmed