Lucene search
+L

TFTP File Transfer Utility

🗓️ 20 Dec 2011 16:06:44Reported by todb <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 48 Views

TFTP file transfer module for Metasploit system with upload and download actions availabl

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##


class MetasploitModule < Msf::Auxiliary
  include Rex::Proto::TFTP
  include Msf::Auxiliary::Report

  def initialize
    super(
      'Name'        => 'TFTP File Transfer Utility',
      'Description' => %q{
          This module will transfer a file to or from a remote TFTP server.
          Note that the target must be able to connect back to the Metasploit system,
          and NAT traversal for TFTP is often unsupported.

          Two actions are supported: "Upload" and "Download," which behave as one might
          expect -- use 'set action Actionname' to use either mode of operation.

          If "Download" is selected, at least one of FILENAME or REMOTE_FILENAME
          must be set. If "Upload" is selected, either FILENAME must be set to a valid path to
          a source file, or FILEDATA must be populated. FILENAME may be a fully qualified path,
          or the name of a file in the Msf::Config.local_directory or Msf::Config.data_directory.
        },
      'Author'      => [ 'todb' ],
      'References'  =>
        [
          ['URL', 'http://www.faqs.org/rfcs/rfc1350.html'],
          ['URL', 'http://www.networksorcery.com/enp/protocol/tftp.htm']
        ],
      'Actions' => [
          [ 'Download', 'Description' => "Download REMOTE_FILENAME as FILENAME from the server."],
          [ 'Upload',   'Description' => "Upload FILENAME as REMOTE_FILENAME to the server."]
        ],
      'DefaultAction' => 'Upload',
      'License'     => MSF_LICENSE
    )
    register_options([
      OptString.new( 'FILENAME', [false, "The local filename" ]),
      OptString.new( 'FILEDATA', [false, "Data to upload in lieu of a real local file." ]),
      OptString.new( 'REMOTE_FILENAME', [false, "The remote filename"]),
      OptAddress.new('RHOST',    [true, "The remote TFTP server"]),
      OptPort.new(   'LPORT',    [false, "The local port the TFTP client should listen on (default is random)" ]),
      OptAddressLocal.new('LHOST',    [false, "The local address the TFTP client should bind to"]),
      OptString.new( 'MODE',     [false, "The TFTP mode; usual choices are netascii and octet.", "octet"]),
      Opt::RPORT(69)
    ])
  end

  def mode
    datastore['MODE'] || "octet"
  end

  def remote_file
    return datastore['REMOTE_FILENAME'] if datastore['REMOTE_FILENAME']
    return ::File.split(datastore['FILENAME']).last if datastore['FILENAME']
  end

  def rport
    datastore['RPORT'] || 69
  end

  def rhost
    datastore['RHOST']
  end

  # Used only to store loot, doesn't actually have any semantic meaning
  # for the TFTP protocol.
  def datatype
    case datastore['MODE']
    when "netascii"
      "text/plain"
    else
      "application/octet-stream"
    end
  end

  def file
    if action.name == "Upload"
      fdata = datastore['FILEDATA'].to_s
      fname = datastore['FILENAME'].to_s
      if not fdata.empty?
        fdata_decorated = "DATA:#{datastore['FILEDATA']}"
      elsif ::File.readable? fname
        fname
      else
        fname_local = ::File.join(Msf::Config.local_directory,fname)
        fname_data  = ::File.join(Msf::Config.data_directory,fname)
        return fname_local if ::File.file?(fname_local) and ::File.readable?(fname_local)
        return fname_data  if ::File.file?(fname_data)  and ::File.readable?(fname_data)
        return nil # Couldn't find it, giving up.
      end
    else # "Download"
      fname = ::File.split(datastore['FILENAME'] || datastore['REMOTE_FILENAME']).last rescue nil
    end
  end

  # Experimental message prepending thinger. Might make it up into the
  # standard Metasploit lib like vprint_status and friends.
  def rtarget(ip=nil)
    if (ip or rhost) and rport
      [(ip || rhost),rport].map {|x| x.to_s}.join(":") << " "
    elsif (ip or rhost)
      "#{rhost} "
    else
      ""
    end
  end

  # This all happens before run(), and should give an idea on how to use
  # the TFTP client mixin. Essentially, you create an instance of the
  # Rex::Proto::TFTP::Client class, fill it up with the relevant host and
  # file data, set it to either :upload or :download, then kick off the
  # transfer as you like.
  def setup
    @lport = datastore['LPORT'] || (1025 + rand(0xffff-1025))
    @lhost = datastore['LHOST'] || "0.0.0.0"
    @local_file = file
    @remote_file = remote_file

    @tftp_client = Rex::Proto::TFTP::Client.new(
      "LocalHost"  => @lhost,
      "LocalPort"  => @lport,
      "PeerHost"   => rhost,
      "PeerPort"   => rport,
      "LocalFile"  => @local_file,
      "RemoteFile" => @remote_file,
      "Mode"       => mode,
      "Context"    => {'Msf' => self.framework, 'MsfExploit' => self},
      "Action"     => action.name.to_s.downcase.intern
    )
  end

  def run
    case action.name
    when 'Upload'
      if file
        run_upload()
      else
        print_error "Need at least a local file name or file data to upload."
        return
      end
    when 'Download'
      if remote_file
        run_download()
      else
        print_error "Need at least a remote file name to download."
        return
      end
    else
      print_error "Unknown action: '#{action.name}'"
    end
    while not @tftp_client.complete
      select(nil,nil,nil,1)
      print_status [rtarget,"TFTP transfer operation complete."].join
      save_downloaded_file() if action.name == 'Download'
      break
    end
  end

  # Run in case something untoward happened with the connection and the
  # client object didn't get stopped on its own. This can happen with
  # transfers that got interrupted or malformed (like sending a 0 byte
  # file).
  def cleanup
    if @tftp_client and @tftp_client.respond_to? :complete
      while not @tftp_client.complete
        select(nil,nil,nil,1)
        vprint_status "Cleaning up the TFTP client ports and threads."
        @tftp_client.stop
      end
    end
  end

  def run_upload
    print_status "Sending '#{file}' to #{rhost}:#{rport} as '#{remote_file}'"
    ret = @tftp_client.send_write_request { |msg| print_tftp_status(msg) }
  end

  def run_download
    print_status "Receiving '#{remote_file}' from #{rhost}:#{rport} as '#{file}'"
    ret = @tftp_client.send_read_request { |msg| print_tftp_status(msg) }
  end

  def save_downloaded_file
    print_status "Saving #{remote_file} as '#{file}'"
    fh = @tftp_client.recv_tempfile
    data = File.open(fh,"rb") {|f| f.read f.stat.size} rescue nil
    if data and not data.empty?
      unless framework.db.active
        print_status "No database connected, so not actually saving the data:"
        print_line data
      end
      this_service = report_service(
        :host => rhost,
        :port => rport,
        :name => "tftp",
        :proto => "udp"
      )
      store_loot("tftp.file",datatype,rhost,data,file,remote_file,this_service)
    else
      print_status [rtarget,"Did not find any data, so nothing to save."].join
    end
    fh.unlink rescue nil # Windows often complains about unlinking tempfiles
  end

  def print_tftp_status(msg)
    case msg
    when /Aborting/, /errors.$/
      print_error [rtarget,msg].join
    when /^WRQ accepted/, /^Sending/, /complete!$/
      print_good [rtarget,msg].join
    else
      vprint_status [rtarget,msg].join
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

07 Jan 2024 20:02Current
7.3High risk
Vulners AI Score7.3
48