Talos Vulnerability Report


Shimo VPN helper tool writeConfig privilege escalation vulnerability

April 15, 2019
CVE Number



An exploitable privilege escalation vulnerability exists in the Shimo VPN helper service in the writeConfig functionality. A non-root user is able to write a file anywhere on the system. A user with local access can use this vulnerability to raise their privileges to root. An attacker would need local access to the machine to exploit it successfully.

Tested Versions

Shimo VPN

Product URLs


CVSSv3 Score

9.3 - CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H


CWE-19: Improper Input Validation


Shimo VPN is a VPN client for Mac OSX used to connect to and manage multiple VPN accounts in one place. The application uses what is defined as a “Helper Tool” to do some of the privileged work on its behalf. The helper tool is installed as root when the application is first installed and is a LaunchD daemon, meaning it will be restarted if it is killed. The service listens using:

v3 = objc_msgSend(&OBJC_CLASS___NSXPCListener, "alloc");
v4 = objc_msgSend(v3, "initWithMachServiceName:", CFSTR("com.feingeist.shimo.helper"));

The second argument registers the string passed in as a service and tells it to begin listening. This opens the service up to be connected to using Objective-C XPC calls. To connect a client to this service, a similar section of code needs to be executed.

 v8 = objc_msgSend(v7, "initWithMachServiceName:options:", CFSTR("com.feingeist.shimo.helper"), 4096LL); [1]
  v11 = objc_msgSend(
          &OBJC_PROTOCOL___ShimoHelperToolProtocol);                                                      [2]

At [1], the same call as the one above is used, except this time, the options variable is used to signify that the client is connecting rather than listening. At [2], a special protocol is passed in, which defines all the functions available to the client. The server must have the same protocol defined in order for these calls to work. We can begin to see the vulnerabilities arise by looking at the protocol.

The next function to look at is called writeConfig:atPath:withReply:. The relevant code is shown below.

  data = arg_3
  path = arg_4
  syslog(5, "Running writeConfig in helper.");
  v9 = objc_msgSend(arg_4, "stringByDeletingLastPathComponent");   [3]

  v12 = objc_msgSend(v11, "fileExistsAtPath:", v27);         [4]

  if (  v12
        objc_msgSend(v14, "createDirectoryAtPath:withIntermediateDirectories:attributes:error:", v27, 1LL, 0LL, &v30)
    v21 = objc_msgSend(v20, "fileExistsAtPath:", v7);
    if ( v21 )
      objc_msgSend(v23, "removeItemAtPath:error:", v7, &v29);       [5]
    objc_msgSend(data, "writeToFile:atomically:encoding:error:", path, 1LL, 4LL, &error);   [6]

Location [3] has a passed in an argument being used to construct a proper string. Then, [4] checks if this argument exists as a file. A directory structure is attempted to be created for it if it does not exist. At [5], the passed-in file is removed if it exists and, finally, at [6], the data passed into the function is written out to the file provided. This allows a non-privileged user to write to a privileged location crossing a privilege boundary and creating a privilege escalation vulnerability.


2018-09-21 - Vendor Disclosure
2018-09-22 - Vendor acknowledged and gave main developer contact
2018-09-26 - Reports sent to main developer
2018-10-08 - First follow up
2018-11-09 - 2nd follow up
2018-12-04 - 3rd follow up
2019-03-14 - Final follow up for public disclosure
2019-04-15 - Zero day/Public release


Discovered by Tyler Bohan of Cisco Talos.