VMware ESXi OpenSLP堆溢出漏洞,附本次勒索软件ESXiArgs恶意文件分析(CNVD-2021-12321对标CVE-2021-21974)
Posted 鸭梨山大。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VMware ESXi OpenSLP堆溢出漏洞,附本次勒索软件ESXiArgs恶意文件分析(CNVD-2021-12321对标CVE-2021-21974)相关的知识,希望对你有一定的参考价值。
近日以VMware ESXi服务器为目标的大规模勒索软件攻击正在席卷全球,包括法国、芬兰、加拿大、美国、意大利等多个国家数千台服务器遭到入侵。攻击者利用了2021年2月公开的高危漏洞(CNVD-2021-12321,https://www.cnvd.org.cn/flaw/show/CNVD-2021-12321),可以向WMware ESXi软件目标服务器427端口发送恶意构造的数据包,从而触发其OpenSLP服务堆缓冲区溢出,并执行任意代码,借以部署新的 ESXiArgs 勒索软件。
一、漏洞详情
VMware vSphere是美国威睿公司推出一套服务器虚拟化解决方案,包括虚拟化、管理和界面层。VMware vSphere的两个核心组件是ESXi服务器和vCenter。VMware ESXi是VMware的裸机虚拟机管理程序,用以创建运行虚拟机和虚拟设备。VMware vCenter Server是管理整个VMware虚拟化基础架构的软件,用于集中管理多个ESXi主机和以及在ESXi主机上运行的虚拟机。
VMware ESXi堆溢出漏洞(CVE-2021-21974):当ESXi在OpenSLP服务中处理数据包时,由于边界错误,本地网络上的远程非身份验证攻击者可以将伪造的数据包发送到427端口,触发基于堆的缓冲区溢出,并在目标系统上执行任意代码。
近期,网络上出现了一种新的勒索软件 ESXiArgs ,该勒索软件于今年2月开始大规模出现。攻击者利用两年前未经修补的 RCE 漏洞 CVE-2021-21974 将恶意文件传输至 ESXi 导致 OpenSLP 服务中的堆溢出。
二、影响范围:
VMware ESXi70U1c-17325551 7.0版本
VMware ESXi670-202102401-SG 6.7版本
VMware ESXi650-202102101-SG6.5版本
受 ESXiArgs 影响 ESXi 服务器涉及版本集中在 6.7.0、6.5.0、6.0.0、5.5.0,但 VMware 关于 CVE-2021-21974 的官方公告并没有具体说明 6.0.0 和 5.5.0 版本是受影响的版本,但是,根据网络空间测绘数据统计该版本明确被攻击。
国内存在该漏洞影响的服务器数量如下所示(基于censys统计数据):
版本 | 数量统计 |
ESXi 6.5 | 715 |
ESXi 6.7 | 3184 |
ESXi 7.0 | 1271 |
ESXi 6.0.0 | 665 |
ESXi 5.0.0 | 342 |
三、漏洞解决办法:
方法一:通过官方补丁,对VMware ESXi进行升级。
VMware官方此前已发布补丁修复此漏洞,参考链接:https://www.vmware.com/security/advisories/VMSA-2021-0002.html
方法二:不具备补丁升级条件的,可以通过关闭OpenSLP服务来规避。
1、登录ESXi,选中左侧导航器的主机,在右侧选择“操作-服务-启用安全Shell(SSH)”;
2、远程登录ESXi主机,文中是通过xshell连接,注意这里的密码要选择Keyboard Interactive,这个账号密码就是你ESXi的账号密码
查看SLP服务状态
/etc/init.d/slpd status
如果显示slpd is running,则表示该服务正常运行中。
停止SLP服务
/etc/init.d/slpd stop
禁用SLP服务
esxcli network firewall ruleset set -r CIMSLP -e 0
查看SLP是否设置了开机自启动
chkconfig --list | grep slpd
7、如果slpd服务为on,则执行以下命令关闭自启动
chkconfig slpd off
四、勒索软件ESXiArgs恶意文件分析
通过分析发现与该勒索行为相关的文件共有5个,位于受害服务器中的/tmp/文件夹下,相关恶意文件及描述如下所示:
encrypt– 加密器(ELF可执行文件)
encrypted.sh – 执行加密器之前的功能文件
public.pem – 用于加密文件的RSA加密算法中的公钥
motd——文本格式的勒索信文件
index.html – html格式的勒索信文件
该样本使用参数进行启动,在程序启动初始阶段便会对参数进行强校验,样本通过正确参数启动后便会进行后续操作,勒索信文件名为 “How to Restore Your Files.html”, 指示受害者通过 TOX_ID 与攻击者取得联系,以恢复加密文件或防止数据被泄露。
encrypt.sh
shell脚本整体逻辑如下所示:
修改配置文件
修改虚拟机的磁盘文件 vmdk 及虚拟内存文件 vswp 的文件名,增加受害者在文件加密后找到和恢复初始数据的困难性。
加密文件
首先枚举 ESXi 主机上所有的存储卷,因此未连接到 VM 的虚拟磁盘可能也会受到影响。
加密存储卷中包含如下扩展名的文件:
*.vmdk
*.vmx
*.vmxf
*.vmsd
*.vmsn
*.vswp
*.vmss
*.nvram
*.vmem
持久化
将 encrypt_file() 勒索信文件复制到 /usr/lib/vmware 目录下
防御规避
该勒索软件为了避免被发现及数据恢复,尝试了如下操作:包括删除系统中所有的 log 文件、清除计划任务、删除备份文件、删除 http 端口配置文件中所有存在的 ip、删除store/packages/vmtools.py后门文件及最初始上传的 tmp/ 目录下的恶意文件。
启动ssh服务
加密器encrypt
启动命令,启动参数包括公共 RSA 密钥文件、要加密的文件路径、避免加密的数据块、加密块的大小和文件大小。
勒索软件启动会执行多个步骤来加密系统文件。
encrypt_file()函数进一步调用encrypt_simple()函数来执行加密过程。下图显示了 encrypt_file()函数的代码片段
encrypt_simple函数如下所示:
sosemanuk_encrypt 加密过程如下所示:
检查存储在 result 中的值是否小于 0x4F,当小于 0x4F时,它将明文的前 80LL - (a1 + 128)字节与 Sosemanuk 密码的内部状态进行异或。然后该函数进入一个循环,每次以 80LL 字节的块加密剩余的明文,在每个块加密后更新 Sosemanuk密码的内部状态。然后将加密块与明文进行异或运算以生成密文。
文件小于 128MB 时,完全加密
文件大于 128MB (1M=1024K)时未完全加密
生成流密钥
ATT&CK
IOCs
ESXi勒索软件支付地址列表
https://gist.github.com/cablej/c79102960c4615396e8ffc712136744a
MD5
d0d36f169f1458806053aae482af5010 encrypt.sh
87b010bc90cd7dd776fb42ea5b3f85d3 encrypt
五、勒索软件ESXiArgs处置建议
上述漏洞解决方案;
检查文件 “vmtools.py” 是否存在于“/store/packages/”位置。如果找到,建议立即删除该文件。
重要的数据最好双机备份。
转:利用一个堆溢出漏洞实现VMware虚拟机逃逸
转:https://zhuanlan.zhihu.com/p/27733895?utm_source=tuicool&utm_medium=referral
利用一个堆溢出漏洞实现VMware虚拟机逃逸
[作者:李小龙(acez),中文翻译:kelwin]
1. 介绍
2017年3月,长亭安全研究实验室(Chaitin Security Research Lab)参加了Pwn2Own黑客大赛,我作为团队的一员,一直专注于VMware Workstation Pro的破解,并成功在赛前完成了一个虚拟机逃逸的漏洞利用。(很不)幸运的是,就在Pwn2Own比赛的前一天(3月14日),VMware发布了一个新的版本,其中修复了我们所利用的漏洞。在本文中,我会介绍我们从发现漏洞到完成利用的整个过程。感谢@kelwin在实现漏洞利用过程中给予的帮助,也感谢ZDI的朋友,他们近期也发布了一篇相关博客,正是这篇博文促使我们完成本篇writeup。
本文主要由三部分组成:首先我们会简要介绍VMware中的RPCI机制,其次我们会描述本文使用的漏洞,最后讲解我们是如何利用这一个漏洞来绕过ASLR并实现代码执行的。
2. VMware RPCI机制
VMware实现了多种虚拟机(下文称为guest)与宿主机(下文称文host)之间的通信方式。其中一种方式是通过一个叫做Backdoor的接口,这种方式的设计很有趣,guest只需在用户态就可以通过该接口发送命令。VMware Tools也部分使用了这种接口来和host通信。我们来看部分相关代码(摘自open-vm-tools中的lib/backdoor/backdoorGcc64.c):
void
Backdoor_InOut(Backdoor_proto *myBp) // IN/OUT
{
uint64 dummy;
__asm__ __volatile__(
#ifdef __APPLE__
/*
* Save %rbx on the stack because the Mac OS GCC doesn‘t want us to
* clobber it - it erroneously thinks %rbx is the PIC register.
* (Radar bug 7304232)
*/
"pushq %%rbx" "\n\t"
#endif
"pushq %%rax" "\n\t"
"movq 40(%%rax), %%rdi" "\n\t"
"movq 32(%%rax), %%rsi" "\n\t"
"movq 24(%%rax), %%rdx" "\n\t"
"movq 16(%%rax), %%rcx" "\n\t"
"movq 8(%%rax), %%rbx" "\n\t"
"movq (%%rax), %%rax" "\n\t"
"inl %%dx, %%eax" "\n\t" /* NB: There is no inq instruction */
"xchgq %%rax, (%%rsp)" "\n\t"
"movq %%rdi, 40(%%rax)" "\n\t"
"movq %%rsi, 32(%%rax)" "\n\t"
"movq %%rdx, 24(%%rax)" "\n\t"
"movq %%rcx, 16(%%rax)" "\n\t"
"movq %%rbx, 8(%%rax)" "\n\t"
"popq (%%rax)" "\n\t"
#ifdef __APPLE__
"popq %%rbx" "\n\t"
#endif
: "=a" (dummy)
: "0" (myBp)
/*
* vmware can modify the whole VM state without the compiler knowing
* it. So far it does not modify EFLAGS. --hpreg
*/
:
#ifndef __APPLE__
/* %rbx is unchanged at the end of the function on Mac OS. */
"rbx",
#endif
"rcx", "rdx", "rsi", "rdi", "memory"
);
}
上面的代码中出现了一个很奇怪的指令inl。在通常环境下(例如Linux下默认的I/O权限设置),用户态程序是无法执行I/O指令的,因为这条指令只会让用户态程序出错并产生崩溃。而此处这条指令产生的权限错误会被host上的hypervisor捕捉,从而实现通信。Backdoor所引入的这种从guest上的用户态程序直接和host通信的能力,带来了一个有趣的攻击面,这个攻击面正好满足Pwn2Own的要求:“在这个类型(指虚拟机逃逸这一类挑战)中,攻击必须从guest的非管理员帐号发起,并实现在host操作系统中执行任意代码”。guest将0x564D5868存入$eax,I/O端口号0x5658或0x5659存储在$dx中,分别对应低带宽和高带宽通信。其它寄存器被用于传递参数,例如$ecx的低16位被用来存储命令号。对于RPCI通信,命令号会被设为BDOOR_CMD_MESSAGE(=30)。文件lib/include/backdoor_def.h中包含了一些支持的backdoor命令列表。host捕捉到错误后,会读取命令号并分发至相应的处理函数。此处我省略了很多细节,如果你有兴趣可以阅读相关源码。
2.1 RPCI
远程过程调用接口RPCI(Remote Procedure Call Interface)是基于前面提到的Backdoor机制实现的。依赖这个机制,guest能够向host发送请求来完成某些操作,例如,拖放(Drag n Drop)/复制粘贴(Copy Paste)操作、发送或获取信息等等。RPCI请求的格式非常简单:<命令> <参数>。例如RPCI请求info-get guestinfo.ip可以用来获取guest的IP地址。对于每个RPCI命令,在vmware-vmx进程中都有相关注册和处理操作。
需要注意的是有些RPCI命令是基于VMCI套接字实现的,但此内容已超出本文讨论的范畴。
3. 漏洞
花了一些时间逆向各种不同的RPCI处理函数之后,我决定专注于分析拖放(Drag n Drop,下面简称为DnD)和复制粘贴(Copy Paste,下面简称为CP)功能。这部分可能是最复杂的RPCI命令,也是最可能找到漏洞的地方。在深入理解的DnD/CP内部工作机理后,可以很容易发现,在没有用户交互的情况下,这些处理函数中的许多功能是无法调用的。DnD/CP的核心功能维护了一个状态机,在无用户交互(例如拖动鼠标从host到guest中)情况下,许多状态是无法达到的。
我决定看一看Pwnfest 2016上被利用的漏洞,该漏洞在这个VMware安全公告中有所提及。此时我的idb已经标上了很多符号,所以很容易就通过bindiff找到了补丁的位置。下面的代码是修补之前存在漏洞的函数(可以看出services/plugins/dndcp/dnddndCPMsgV4.c中有对应源码,漏洞依然存在于open-vm-tools的git仓库的master分支当中):
static Bool DnDCPMsgV4IsPacketValid(const uint8 *packet,
size_t packetSize)
{
DnDCPMsgHdrV4 *msgHdr = NULL;
ASSERT(packet);
if (packetSize < DND_CP_MSG_HEADERSIZE_V4) {
return FALSE;
}
msgHdr = (DnDCPMsgHdrV4 *)packet;
/* Payload size is not valid. */
if (msgHdr->payloadSize > DND_CP_PACKET_MAX_PAYLOAD_SIZE_V4) {
return FALSE;
}
/* Binary size is not valid. */
if (msgHdr->binarySize > DND_CP_MSG_MAX_BINARY_SIZE_V4) {
return FALSE;
}
/* Payload size is more than binary size. */
if (msgHdr->payloadOffset + msgHdr->payloadSize > msgHdr->binarySize) { // [1]每个包的binarySize可以手动设置,但是程序默认为不修改。
return FALSE;
}
return TRUE;
}
Bool
DnDCPMsgV4_UnserializeMultiple(DnDCPMsgV4 *msg,
const uint8 *packet,
size_t packetSize)
{
DnDCPMsgHdrV4 *msgHdr = NULL;
ASSERT(msg);
ASSERT(packet);
if (!DnDCPMsgV4IsPacketValid(packet, packetSize)) {//检查长度
return FALSE;
}
msgHdr = (DnDCPMsgHdrV4 *)packet;
/*
* For each session, there is at most 1 big message. If the received
* sessionId is different with buffered one, the received packet is for
* another another new message. Destroy old buffered message.
*/
if (msg->binary &&
msg->hdr.sessionId != msgHdr->sessionId) {
DnDCPMsgV4_Destroy(msg);
}
/* Offset should be 0 for new message. */
if (NULL == msg->binary && msgHdr->payloadOffset != 0) {
return FALSE;
}
/* For existing buffered message, the payload offset should match. */
if (msg->binary &&
msg->hdr.sessionId == msgHdr->sessionId &&
msg