CVE-2021-22005分析

    渗透测试 lz520520 2年前 (2022-03-20) 745次浏览

    2021-09-21补丁修复了如下一系列漏洞,其中CVE-2021-22005评分最高,可getshell,网上也有该漏洞的poc,所以接下来也对该漏洞做进一步分析。

    参考

    任意文件上传

    https://censys.io/blog/vmware-cve-2021-22005-technical-impact-analysis/

    https://github.com/knownsec/pocsuite3/blob/master/pocsuite3/pocs/20210923_WEB_Vmware_vCenter_Server_FIleUpload_CVE-2021-20050.py

    https://testbnull.medium.com/quick-note-of-vcenter-rce-cve-2021-22005-4337d5a817ee

    https://mp.weixin.qq.com/s/gVsxziLqRQzb7QVOfyuBKw

    https://mp.weixin.qq.com/s/Jwp4GWKRO4H_AopqJSrBWw

    官方提供的测试脚本,算是一个漏洞扫描+临时补丁

    https://kb.vmware.com/sfc/servlet.shepherd/version/download/0685G00000YTpbRQAT

    根据提示漏洞接口应该如下

    vmware公开的poc

    影响范围

    漏洞分析

    TelemetryLevelBasedTelemetryServiceWrapper请求入口

    根据poc提示接口/analytics/telemetry/ph/api/hyper/send,找到对应的类

    这个类是springboot的controller,找到漏洞URI,可以看到提交的两个参数_c_i对应的是collectorId和collectorInstanceId

    CVE-2021-22005分析

    继续跟踪到TelemetryLevelBasedTelemetryServiceWrapper#processTelemetry

    TelemetryLevelBasedTelemetryServiceWrapper是在AsyncTelemetryServiceWrapper$TelemetryRequestProcessorRunnable类里调用,这个类是Runnable实现类,用于多线程调用,所以通过该类的run方法进一步跟踪到processTelemetry的。

    生成一个Telemetrylevel对象,TelemetryLevel是一个枚举类型,这里会判断TelemetryLevel.OFF是否不等,继续看一下OFF是怎么设置的

    CVE-2021-22005分析

    调用堆栈

    CVE-2021-22005分析

    ceip

    getTelemetryLevel

    CVE-2021-22005分析

    this._telemetryLevelService.getTelemetryLevel定位到如下,可以看到这里会判断ceip(Customer Experience Improvement Program)是否开启

    DefaultTelemetryLevelService

    CVE-2021-22005分析

    其实ceip是客户体验提升计划,不一定开启。点击加入开启后,其实对提交的_C是有要求的

    CVE-2021-22005分析

    如下_C为111返回还是off,所以参数有要求的

    CVE-2021-22005分析

    查看漏洞利用目录/var/log/vmware/analytics/prod下有一个json文件

    CVE-2021-22005分析

    其实是如此拼接成的,所以

    再次测试可发现返回FULL了

    CVE-2021-22005分析

    或者通过该接口请求测试是否正常,这个请求会生成ceip缓存,后续请求就不会再发送ceip到vmware了。


    这里再继续分析下getTelemetryLevel,他会先判断ceip是否开启,如果没开启,则直接返回OFF,如果为true,则进行判断。

    这里有个变量this._collectorToTelemetryLevelCache来存储collectorAgent对象(基于_c_i生成),如果缓存里有了,就不会再次发遥测请求,_collectorToTelemetryLevelCache在这里是SimpleTimeBasedCacheImpl类,内部实际存储collectorAgent是用的hashmap。

    CVE-2021-22005分析

    CVE-2021-22005分析

    这里通过get获取key(即collectorAgent),所以看看hashCode怎么实现的。

    其实可以看到和_collectorId_collectorInstanceId都相关。

    做个测试,_c_i,如下就是不同缓存

    CVE-2021-22005分析

    getTelemetryLevelFromManifest

    CVE-2021-22005分析

    那么再看看DefaultTelemetryLevelService#getTelemetryLevelFromManifest怎么发送遥测请求的,代码如下

    CVE-2021-22005分析

    manifestContentProvider.getManifestContent请求返回有以下几种情况

    1. collectorId和collectorInstanceId随机,抛出异常,INVALID_COLLECTOR_ERROR,这里提示collectors ID不在白名单内

    CVE-2021-22005分析

    1. collectorId为vSphere.vapi.6_7,抛出异常,GENERAL_ERROR,404

    CVE-2021-22005分析

    1. 再第一次请求后,如果修改参数_i(collectorInstanceId),后续二次请求都会报这个错

    CVE-2021-22005分析

    上面请求最终跟踪到如下位置com.vmware.ph.upload.rest.PhRestClientImpl#getManifest,GET请求

    CVE-2021-22005分析

    手动发送,和之前获取的确实一样。

    CVE-2021-22005分析

    有效请求

    CVE-2021-22005分析

    PS: 这里在处理返回数据,会调用json进行反序列化,转换成com.vmware.ph.model.exceptions.ServiceException

    CVE-2021-22005分析

    DefaultTelemetryLevelService#getTelemetryLevelFromManifest,我们看下抛出异常后再次调用getTelemetryLevelForFailedManifestRetrieval,如果异常是INVALID_COLLECTOR_ERROR,那么直接返回OFF,如果不是就返回FULL,defaultTelemetryLevel初始化的时候为FULL。

    所以如果首次请求的collectorId不对,那么即时开了ceip也是无法利用成功,但第二次还是可以成功,所以网上一些分析文章collectorId随机也是可以用的,但如果之前没有发送过遥测请求,就会利用失败,所以建议collectorId还是设置一个有效的。

    CVE-2021-22005分析

    开启ceip

    经过测试,开启CEIP的接口无认证要求,可未授权访问

    PS: 但上面这个测试如果系统启动后没有登录过,请求不会成功

    调试发现,虽然接口请求不需要认证,但修改操作仍然需要session,只有在有人登录过,这个未授权请求才能生效。

    CVE-2021-22005分析

    该请求对应的类在./plugin-packages/telemetry/plugins/h5-ceip.war

    com.vmware.vsphere.client.h5.ceip.controller.CeipController

    CVE-2021-22005分析

    还有其他两个接口

    LogTelemetryService

    所以看来CEIP没有比较好的方案开启了。

    CVE-2021-22005分析

    当ceip开启,继续跟踪到com/vmware/ph/phservice/push/telemetry/LogTelemetryService#processTelemetry

    CVE-2021-22005分析

    日志目录是/var/log/vmware/analytics/prod

    CVE-2021-22005分析

    日志文件名则是,可以看到

    CVE-2021-22005分析

    继续往下就是日志记录,this._logger可以看到日志路径,而serializeToLogMessage(telemetryRequest)就是POST请求的body数据

    CVE-2021-22005分析

    那么当请求参数_c=vSphere.vapi.6_7&_i=/../../../../../../tmp/foo

    则拼接为/var/log/vmware/analytics/prod/_cvSphere.vapi.6_7_i/../../../../../../tmp/foo.json

    但如果_cvSphere.vapi.6_7_i不存在,则会目录遍历失败,这个是linux的问题,所以必须先请求一次_c=vSphere.vapi.6_7&_i=/temp,log4j会创建目录,然后再请求上面URL,实现目录遍历。

    CVE-2021-22005分析

    PS: prod目录默认也是没有的,vcenter自身正常会创建这个prod目录,但ceip没开启之前,是没有的,所以建议也请求下正常的参数。

    创建prod目录

    创建_cvSphere.vapi.6_7_i目录

    由于后缀只能是json,所以无法直接写文件,那么可以写到一个可执行文件内容的路径,这个大家就自行发挥想象力找找linux上可执行的方法了。

    整理思路

    1. AsyncTelemetryController是/analytics/telemetry/ph/api/hyper/send请求处理入口,接收_c_i参数
    2. 调用TelemetryLevelBasedTelemetryServiceWrapper#processTelemetry 发起ceip遥测请求,,成功后进一步处理_c_i
    3. processTelemetry里调用this._telemetryLevelService.getTelemetryLevel来判断ceip遥测请求是否正常,这里也会传入_c_i,如果开启成功可获取一个FULL值,除了需要开启ceip,还会对vmware的一个API接口发送请求,,需要注意的一点,如果之前没发起遥测请求,则对_c参数有要求,必须是一个合法的值,如果已经请求过,后续因为有缓存,不会再请求,则可成功通过校验。
    4. 如果ceip未开启,可通过/ui/ceip-ui/ctrl/ceip/status/true开启,但vcenter之前需要有人已经登录过一次,否则会出现接口未认证的报错。
    5. ceip请求成功后,processTelemetry接着调用LogTelemetryService#processTelemetry来解析_c_i,log4j通过_c$s_i$s格式拼接日志路径,_i设置成如/../../../../../../tmp/test即可导致任意路径遍历写入文件,当_c=vSphere.vapi.6_7&_i=/../../../../../../tmp/test最终路径拼接如/var/log/vmware/analytics/prod/_cvSphere.vapi.6_7_i/../../../../../../tmp/foo.json,这里需要注意的是linux上目录遍历时需要遍历前的上级目录存在才可遍历。

      验证

      返回201表示漏洞存在

      利用

      第一步判断ceip

      CVE-2021-22005分析

    CVE-2021-22005分析

    /var/log/vmware/analytics/prod创建 prod_cvSphere.vapi.6_7_i

    _i参数每次都要修改,因为文件如果被删除,就不会再次被创建了

    CVE-2021-22005分析

    写任意路径文件

    补丁分析

    补丁包

    VMware-analytics-6.7.0-18408195.x86_64.rpm,解压出来就是各种jar包和其他一些配置文件,对比jar包,定位到如下

    CVE-2021-22005分析

    对比补丁,补丁在AsyncTelemetryController#handleSendRequest里新增了一个条件判断

    CVE-2021-22005分析

    判断语句

    IdFormatUtil.class在analytics-6.7.0.jar里

    collectorInstanceId正则过滤[\\w-]{1,64} =[A-Za-z0-9_-]{1,64},如9D36C850-1612-4EC4-B8DD-50BA239A25BB,没法使用.和/,所以这个绕不过了

    collectorId [a-zA-Z][\w-\.]{1,40}[a-zA-Z0-9], 如vSphere.vapi.6_7,也没法使用/,但没调用。

    CVE-2021-22005分析

    collectorId是用一个白名单,需要调试才能最终确定白名单内容,但根据上面的正则也能大致猜测,这里的白名单估计和之前ceip 遥测请求的API接口是一样的。

    this._collectorIdWhitelist为在控制器初始化的传入

    CVE-2021-22005分析

    另外除了公开的漏洞利用点之外,AsyncTelemetryController还有两个私有类也有patch,都是Callable的实现类(即多线程),这里会检查collectorId

    CVE-2021-22005分析

    另一个和之前漏洞点判断是一样的。

    CVE-2021-22005分析

    那么是否可以找到其他没做过滤的telemetryService.processTelemetry调用点,在这之前其实还需要检查下processTelemetry内部是否还有patch。

    这里调用的实现类是TelemetryLevelBasedTelemetryServiceWrapper,另一个相关的是LogTelemetryService

    TelemetryLevelBasedTelemetryServiceWrapper在analytics-6.7.0.jar里,但对比了补丁,没发现直接的改动。

    但有其他几处DataAppAgentId做了相同的过滤,这就涉及到另一个漏洞点了。

    LogTelemetryService在同个包里,也没做修改。

    CVE-2021-22005分析


    Security , 版权所有丨如未注明 , 均为原创丨
    转载请注明原文链接:CVE-2021-22005分析
    喜欢 (2)