Talos Vulnerability Report

TALOS-2018-0674

Shimo VPN helper tool configureRoutingWithCommand privilege escalation vulnerability

April 15, 2019
CVE Number

CVE-2018-4005

Summary

An exploitable privilege escalation vulnerability exists in the Shimo VPN 4.1.5.1 helper service in the configureRoutingWithCommand function. A user with local access can use this vulnerability to raise their privileges to root. An attacker would need local access to the machine for a successful exploit.

Tested Versions

Shimo VPN 4.1.5.1

Product URLs

https://www.shimovpn.com/

CVSSv3 Score

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

CWE

CWE-19: Improper Input Validation

Details

Shimo VPN is a VPN client for Mac OSX used to connect to 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. A similar section of code needs to be executed to connect a client to this service.

 v8 = objc_msgSend(v7, "initWithMachServiceName:options:", CFSTR("com.feingeist.shimo.helper"), 4096LL); [1]
  v11 = objc_msgSend(
          &OBJC_CLASS___NSXPCInterface,
          "interfaceWithProtocol:",
          &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 that 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 protocols.

The function configureRoutingWithCommand:withReply: is available in the described protocol and is vulnerable to a privilege escalation attack. The function takes a string as an argument and executes it in root context as a bash script. The relevant code is shown below.

  user_supplied_arg = objc_retain(arg_3, a2);                      [1]
  v6 = objc_retain(v4, a2);
  syslog(5, "Running configureRoutingWithCommand in helper.");
  if ( user_supplied_arg )
  {
    user_data_to_write = user_supplied_arg;
    v7 = objc_msgSend(self->tmpDirPath, "stringByAppendingPathComponent:", CFSTR("shimo_routing.sh"));   [2]
    path = objc_retainAutoreleasedReturnValue(v7);
    v11 = objc_msgSend(v10, "fileExistsAtPath:", path_);

    ...

      objc_msgSend(user_data_to_write, "writeToFile:atomically:encoding:error:", path, 1LL, 4LL, &error); [3]
      v18 = objc_retain(error, "writeToFile:atomically:encoding:error:");
      objc_release(error_);

      ...
          v26 = objc_msgSend(&OBJC_CLASS___NSTask, "alloc");
          v27 = objc_msgSend(v26, "init");
          objc_msgSend(v27, "setLaunchPath:", path, v27);
          (objc_msgSend)(v27, "setCurrentDirectoryPath:", self->tmpDirPath);
          v28 = (objc_msgSend)(&OBJC_CLASS___NSPipe, "pipe");
          v43 = objc_retainAutoreleasedReturnValue(v28);
          objc_msgSend(v27, "setStandardOutput:", v43);
          objc_msgSend(v27, "launch");                          [4]

At [1], data is passed into the function call and stored for later use. A path is then constructed at [2], pointing to a file named shimo_routing.sh. At [3], the data passed into the function is then used to write to the file mentioned previously. Finally at [4], this newly created script is launched in the root context, allowing a non-privileged user root access and creating a privilege escalation scenario.

Exploit Proof of Concept

The configureRouting executable provided will launch a script at /tmp/root.py. The attached example script to be launched from that location expresses the gravity of this issue. To set up proper testing a non-privileged user needs to move the included root.py script to /tmp and perform the command chmod +x /tmp/root.py to ensure to script is executable. The script will attempt to connect back to a provided IP for a root shell and will also place a file in the root directory to show a successful attack.

Timeline

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

Credit

Discovered by Tyler Bohan of Cisco Talos.