vCenter 6.5-7.0 RCE 漏洞分析(CVE-2021-21972) – 作者:BIGLucifer

0x01. 漏洞介绍

vCenter Server 为 ESXi 的控制中心,可从单一控制点统一管理数据中心的所有 vSphere 主机和虚拟机。

CVE-2021-21972 是Vcenter的一个未授权文件上传漏洞。该漏洞可以上传文件至vcenter服务器的任意位置。由于该服务System权限,可以任意写,可上传webshell并执行,如果是Linux环境并开放了ssh,可上传公钥直接通过ssh登录。

0x02. 漏洞分析

环境搭建过程可以参考:https://www.miensi.com/352.html

vCenter Server 的 vROPS 插件的 API 采用spring编写。部分敏感接口未经过鉴权,其中uploadova接口存在一个上传 OVA 文件的功能:

@RequestMapping(
        value = {"/uploadova"},
        method = {RequestMethod.POST}
    )
    public void uploadOvaFile(@RequestParam(value = "uploadFile",required = true) CommonsMultipartFile uploadFile, HttpServletResponse response) throws Exception {
        logger.info("Entering uploadOvaFile api");
        int code = uploadFile.isEmpty() ? 400 : 200;
        PrintWriter wr = null;
...
        response.setStatus(code);
        String returnStatus = "SUCCESS";
        if (!uploadFile.isEmpty()) {
            try {
                logger.info("Downloading OVA file has been started");
                logger.info("Size of the file received  : " + uploadFile.getSize());
                InputStream inputStream = uploadFile.getInputStream();
                File dir = new File("/tmp/unicorn_ova_dir");
                if (!dir.exists()) {
                    dir.mkdirs();
                } else {
                    String[] entries = dir.list();
                    String[] var9 = entries;
                    int var10 = entries.length;

                    for(int var11 = 0; var11 < var10; ++var11) {
                        String entry = var9[var11];
                        File currentFile = new File(dir.getPath(), entry);
                        currentFile.delete();
                    }

                    logger.info("Successfully cleaned : /tmp/unicorn_ova_dir");
                }

                TarArchiveInputStream in = new TarArchiveInputStream(inputStream);
                TarArchiveEntry entry = in.getNextTarEntry();
                ArrayList result = new ArrayList();
while(entry != null) {
                    if (entry.isDirectory()) {
                        entry = in.getNextTarEntry();
                    } else {
                        File curfile = new File("/tmp/unicorn_ova_dir", entry.getName());
                        File parent = curfile.getParentFile();
                        if (!parent.exists()) {
                            parent.mkdirs();

目的是将 TAR 文件解压后上传到/tmp/unicorn_ova_dir目录,直接将 tar 文件名与/tmp/unicorn_ova_dir拼接并写入文件。

因此文件名中包含../绕过当前目录限制,上传文件至任意位置。

通常情况下可以在目标服务器上写入 JSP webshell 文件(服务是 System 权限,可以任意文件写),利用工具 https://github.com/NS-Sp4ce/CVE-2021-21972

如果环境为Linux且开放了ssh,可以创建一个包含../../home/vsphere-ui/.ssh/authorized_keys的 tar 文件并上传,通过ssh登陆:

$ ssh 10.211.55.4 -lvsphere-ui

VMware vCenter Server 7.0.1.00100

Type: vCenter Server with an embedded Platform Services Controller

vsphere-ui@bogon [ ~ ]$ id
uid=1016(vsphere-ui) gid=100(users) groups=100(users),59001(cis)

0x03 检测poc

#!/usr/bin/env python
# coding: utf-8
from urllib.parse import urljoin

from pocsuite3.api import POCBase, Output, register_poc, logger, requests


class DemoPOC(POCBase):
    vulID = ''
    version = '1.0'
    author = ['']
    vulDate = '2021-02-24'
    createDate = '2021-02-24'
    updateDate = '2021-02-24'
    references = ['']
    name = 'VMware vCenter 未授权RCE漏洞'
    appPowerLink = ''
    appName = 'VMware vCenter'
    appVersion = ' 7.0 U1c 之前的 7.0 版本、6.7 U3l 之前的 6.7 版本、 6.5 U3n 之前的 6.5 版本'
    vulType = ''
    desc = '''
    VMware vCenter 未授权RCE漏洞
    '''
    samples = ['']
    install_requires = ['']

    def _verify(self):
        result = {}

        try:
            vul_url = urljoin(self.url, "/ui/vropspluginui/rest/services/uploadova")
            resp1 = requests.get(self.url)
            resp2 = requests.get(vul_url)
            if '/vsphere-client' in resp1.text and resp2.status_code == 405:
                result['VerifyInfo'] = {}
                result['VerifyInfo']['URL'] = self.url
        except Exception as e:
            logger.error(e)

        return self.parse_output(result)

    def _attack(self):
        return self._verify()

    def parse_output(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('Internet nothing returned')
        return output


register_poc(DemoPOC)

0x04 修复方式

vmware修复方法比较简单,直接关闭插件。

https://kb.vmware.com/s/article/82374

0x05 参考

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

https://www.miensi.com/352.html

https://github.com/NS-Sp4ce/CVE-2021-21972

https://github.com/conjojo/VMware_vCenter_UNAuthorized_RCE_CVE-2021-21972/blob/master/VMware_vCenter_UNAuthorized_RCE.py

来源:freebuf.com 2021-02-25 17:59:54 by: BIGLucifer

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论