Path: blob/master/modules/auxiliary/scanner/ftp/ftp_anonymous.rb
70334 views
# frozen_string_literal: true12##3# This module requires Metasploit: https://metasploit.com/download4# Current source: https://github.com/rapid7/metasploit-framework5##67class MetasploitModule < Msf::Auxiliary8include Msf::Exploit::Remote::Ftp9include Msf::Auxiliary::Scanner10include Msf::Module::Deprecated11moved_from 'auxiliary/scanner/ftp/anonymous'1213def initialize14super(15'Name' => 'Anonymous FTP Access Detection',16'Description' => 'Detect anonymous (read/write) FTP service access.',17'References' => [18['URL', 'https://en.wikipedia.org/wiki/File_Transfer_Protocol#Anonymous_FTP'],19['CVE', '1999-0497'],20],21'Author' => [22'Matteo Cantoni <goony[at]nothink.org>',23'g0tmi1k' # @g0tmi1k - additional features24],25'License' => MSF_LICENSE,26'Notes' => {27'Stability' => [CRASH_SAFE],28'SideEffects' => [IOC_IN_LOGS],29'Reliability' => []30}31)3233register_options(34[35Opt::RPORT(21),36OptBool.new('STORE_LOOT', [false, 'Store the directory listing as loot', true])37]38)39end4041def run_host(target_host)42res = connect_login(true, false)4344if res45dir = Rex::Text.rand_text_alpha(8)46vprint_status("Testing write access, creating test directory: #{dir}")47# Alt would be to use STOR48write_check = send_cmd(['MKD', dir], true)4950if write_check && write_check =~ /^2/51access_type = 'Read/Write'52vprint_status("Removing test directory: #{dir}")53send_cmd(['RMD', dir], true)54else55access_type = 'Read-only'56end5758print_good("Anonymous #{access_type} access (#{@banner_version})")5960if datastore['STORE_LOOT']61vprint_status('Listing directory contents')62listing = send_cmd_data(['LS'], nil)63if listing.nil?64print_warning('Could not retrieve directory listing (data connection failed)')65elsif listing[1].nil? || listing[1].empty?66vprint_status('Directory listing: (empty)')67else68vprint_status("Directory listing:\n#{listing[1]}")69path = store_loot('ftp.anonymous', 'text/plain', rhost, listing[1], 'ftp_anonymous.txt', 'Anonymous FTP directory listing')70print_good("Directory listing stored to: #{path}")71end72end7374report_vuln(75host: rhost,76port: rport,77proto: 'tcp',78sname: 'ftp',79name: 'Anonymous FTP Access',80info: "Anonymous FTP login accepted with #{access_type} access",81refs: references82)83register_creds(target_host, access_type)84elsif banner85print_warning("FTP service, but no anonymous access (#{banner_version})")86else87vprint_warning('No FTP banner received')88end89rescue ::Rex::TimeoutError, ::Rex::ConnectionError, ::EOFError, ::Errno::ECONNREFUSED => e90vprint_error(e.message)91report_host(host: rhost)92rescue ::Interrupt93raise $ERROR_INFO94ensure95disconnect96end9798def register_creds(target_host, access_type)99# Build service information100service_data = {101address: target_host,102port: rport,103service_name: 'ftp',104protocol: 'tcp',105workspace_id: myworkspace_id106}107108# Build credential information109credential_data = {110origin_type: :service,111module_fullname: fullname,112private_data: datastore['FTPPASS'],113private_type: :password,114username: datastore['FTPUSER'],115workspace_id: myworkspace_id116}117118credential_data.merge!(service_data)119credential_core = create_credential(credential_data)120121# Assemble the options hash for creating the Metasploit::Credential::Login object122login_data = {123access_level: access_type,124core: credential_core,125last_attempted_at: DateTime.now,126status: Metasploit::Model::Login::Status::SUCCESSFUL,127workspace_id: myworkspace_id128}129130login_data.merge!(service_data)131create_credential_login(login_data)132end133end134135136