Lucene search
+L

NAT-PMP Port Mapper

🗓️ 24 Jan 2012 16:32:30Reported by Jon Hart <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 17 Views

NAT-PMP Port Mapper module for Metasploit, used to forward TCP and UDP ports on NAT device

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

class MetasploitModule < Msf::Auxiliary
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::NATPMP
  include Rex::Proto::NATPMP

  def initialize
    super(
      'Name'        => 'NAT-PMP Port Mapper',
      'Description' => 'Map (forward) TCP and UDP ports on NAT devices using NAT-PMP',
      'Author'      => 'Jon Hart <jhart[at]spoofed.org>',
      'License'     => MSF_LICENSE
    )

    register_options(
      [
        OptString.new('EXTERNAL_PORTS', [true, 'The external ports to forward from (0 to let the target choose)', 0]),
        OptString.new('INTERNAL_PORTS', [true, 'The internal ports to forward to', '22,135-139,80,443,445'])
      ],
      self.class
    )
  end

  def build_ports(ports_string)
    # We don't use Rex::Socket.portspec_crack because we need to allow 0 and preserve order
    ports = []
    ports_string.split(/[ ,]/).map { |s| s.strip }.compact.each do |port_part|
      if /^(?<port>\d+)$/ =~ port_part
        ports << port.to_i
      elsif /^(?<low>\d+)\s*-\s*(?<high>\d+)$/ =~ port_part
        ports |= (low..high).to_a.map(&:to_i)
      else
        fail ArgumentError, "Invalid port specification #{port_part}"
      end
    end
    ports
  end

  def setup
    super
    @external_ports = build_ports(datastore['EXTERNAL_PORTS'])
    @internal_ports = build_ports(datastore['INTERNAL_PORTS'])

    if @external_ports.size > @internal_ports.size
      fail ArgumentError, "Too many external ports specified (#{@external_ports.size}); " +
        "must be one port (0) or #{@internal_ports.size} ports"
    end

    if @external_ports.size < @internal_ports.size
      if @external_ports != [0]
        fail ArgumentError, "Incorrect number of external ports specified (#{@external_ports.size}); " +
          "must be one port (0) or #{@internal_ports.size} ports"
      else
        @external_ports = [0] * @internal_ports.size
      end
    end
  end

  def run_host(host)
    begin

      udp_sock = Rex::Socket::Udp.create({
        'LocalHost' => datastore['CHOST'] || nil,
        'Context'   => {'Msf' => framework, 'MsfExploit' => self}
      })
      add_socket(udp_sock)

      external_address = get_external_address(udp_sock, host, datastore['RPORT']) || host

      @external_ports.each_index do |i|
        external_port = @external_ports[i]
        internal_port = @internal_ports[i]

        actual_ext_port = map_port(udp_sock, host, datastore['RPORT'], internal_port, external_port, Rex::Proto::NATPMP.const_get(protocol), lifetime)
        map_target = Rex::Socket.source_address(host)
        requested_forwarding = "#{external_address}:#{external_port}/#{protocol}" +
                              " -> " +
                              "#{map_target}:#{internal_port}/#{protocol}"
        if actual_ext_port
          map_target = datastore['CHOST'] ? datastore['CHOST'] : Rex::Socket.source_address(host)
          actual_forwarding = "#{external_address}:#{actual_ext_port}/#{protocol}" +
                                " -> " +
                                "#{map_target}:#{internal_port}/#{protocol}"
          if external_port == 0
            print_good("#{actual_forwarding} forwarded")
          else
            if (external_port != 0 && external_port != actual_ext_port)
              print_good("#{requested_forwarding} could not be forwarded, but #{actual_forwarding} could")
            else
              print_good("#{requested_forwarding} forwarded")
            end
          end
        else
          print_error("#{requested_forwarding} could not be forwarded")
        end

        report_service(
          :host   => host,
          :port   => datastore['RPORT'],
          :proto  => 'udp',
          :name  => 'natpmp',
          :state => Msf::ServiceState::Open
        )
      end
    rescue ::Interrupt
      raise $!
    rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused
      nil
    rescue ::Exception => e
      print_error("Unknown error: #{e.class} #{e.backtrace}")
    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.5High risk
Vulners AI Score7.5
17