Attackers Target Exposed Docker Remote API Servers With perfctl Malware

Attackers are exploiting exposed Docker Remote API servers to deploy the perfctl malware. The attack involves probing for the server, creating a Docker container with the "ubuntu:mantic-20240405" image, and executing a Base64 encoded payload. The payload escapes the container using the "nsenter" command, creates a bash script, and sets environment variables. It then downloads a malicious binary disguised as a PHP extension, employing evasion techniques to avoid detection. The malware uses persistence strategies such as creating a systemd service or a cron job. To mitigate these risks, securing Docker Remote API servers with strong access controls, monitoring for unauthorized activities, and adhering to container security best practices are essential. Regular updates and security audits are also recommended to enhance overall security posture.
The attack on exposed Docker Remote API servers began with the attackers probing for these vulnerable services, which allowed them to gain initial access. BlueRock's Container Capability Control effectively mitigates this step by securing external-facing remote services, preventing unauthorized access. Once access was gained, the attackers deployed a Docker container using a specific image, and executed a Base64 encoded payload. The payload attempted to escape the container using the 'nsenter' command to access the host's namespaces. BlueRock's Namespace Execution Guard is designed to prevent such container escape attempts, ensuring that even if a container is compromised, the host remains secure. These mechanisms collectively enhance the security posture against such sophisticated attacks by controlling container capabilities and preventing unauthorized namespace execution.
- T1133: External Remote Services: The attackers began their campaign by probing for exposed Docker Remote API servers. This technique is consistent with leveraging exposed remote services to gain initial access.
- T1610: Deploy Container: Once the attackers confirmed the presence of the Docker Remote API server, they created a Docker container using a specific image from Docker Hub. This technique involves deploying a container to execute further actions.
- T1059.004: Command and Scripting Interpreter: Unix Shell: After creating the Docker container, the attackers executed a Base64 encoded payload using the Docker Exec API. This technique involves using a command and scripting interpreter to execute malicious commands.
- T1611: Escape to Host: The payload attempted to escape the container by using the 'nsenter' command to enter the host's namespaces, which is indicative of a container escape technique.
- T1543.002: Create or Modify System Process: Systemd Service: The attackers created a systemd service for persistence if systemd was running in non-offline mode. This technique involves creating or modifying system processes to maintain persistence.
- T1053.003: Scheduled Task/Job: Cron: As a fallback persistence mechanism, the attackers set up a cron job, which is another method of maintaining persistence through scheduled tasks.
- T1036.005: Masquerading: Match Legitimate Name or Location: To avoid detection, the attackers named the container 'kube-edagent' to masquerade as a legitimate container, matching legitimate names or locations.
- T1082: System Information Discovery: The attackers gathered system information by checking for multiple running processes and active TCP connections, which is indicative of system information discovery.
- T1132.001: Data Encoding: Standard Encoding: The payload included a Base64 encoded shell script, which is a form of standard data encoding used to obfuscate the malicious commands.
- T1105: Ingress Tool Transfer: The attackers downloaded a malicious binary disguised as a PHP extension using a custom function, which is consistent with ingress tool transfer.
F1: Detailed attack sequence exploiting an exposed Docker Remote API to deploy perfctl
malware, including container escape, payload execution, and persistence establishment.
- Attacker probes the target network to identify an exposed Docker Remote API server. (Cited from: "The sequence of events in this planned attack campaign begins with a ping to the Docker Remote API server")
- Attacker sends a request to the exposed Docker API to create a new container named
kube-edagent
using theubuntu:mantic-20240405
image. (Cited from: "A container named "kube-edagent” was created from the ubuntu:mantic-20240405 base image", "deliberately giving it a name similar to a legitimate container")- BR-57: Cluster Drift Protection - This mechanism is applicable because it prevents unauthorized deployment of new pods/containers outside the standard control plane (like the Kubernetes API). While the attack uses the Docker API directly, in a K8s context, this could be seen as bypassing the K8s scheduler and API server, which BR-57 aims to prevent.
- BR-61: Container Runtime Socket Protection - This mechanism is applicable IF the attacker somehow gained host access first and was using the local Docker socket (
containerd.sock
,docker.sock
) to create the container, AND the attacking process lineage didn't originate from kubelet. The article describes using the remote network API, making BR-61 less directly applicable to this specific initial step, but relevant to preventing misuse of the local socket. - BR-47: Container Capability Control - This mechanism is applicable because it allows enforcing policies on container creation, potentially blocking the creation of containers that request excessive capabilities or privileged mode, even if initiated via the Docker API.
- The container is configured to run in privileged mode (
Privileged: true
) and share the host's PID namespace (pid mode: host
). (Cited from: "They configure the container to operate in privileged mode by setting "Privileged" to "true." They also utilize "pid mode: host," allowing the container to share the Process ID (PID) namespace of the host system.")- BR-47: Container Capability Control - This mechanism is applicable because it allows administrators to define and enforce specific, limited capabilities for containers, overriding requests for full privileged mode (
Privileged: true
). It can prevent containers from running with unnecessary high privileges required for subsequent steps likensenter
. - BR-67: Container Root User Control - This mechanism is applicable as running in privileged mode often implies running processes as root. BR-67 detects and can prevent non-init processes from running as root within the container, reducing the impact of privileged mode.
- BR-49: Namespace Execution Guard - While BR-49 primarily blocks
nsenter
usage, configuring a container withpid mode: host
is a prerequisite often used to facilitate such escapes. Preventing the creation of containers with host PID namespace sharing aligns with the goal of preventing namespace escapes.
- BR-47: Container Capability Control - This mechanism is applicable because it allows administrators to define and enforce specific, limited capabilities for containers, overriding requests for full privileged mode (
- A simple command (
sleep 9955
) is set to run within the container, likely for later process identification. (Cited from: "with “sleep 9955" specified as the command to be executed once the container is up and running. The "sleep" command is used to identify the container process when running the "ps" command.") - If the specified Ubuntu image is not present, the attacker ensures it is pulled from Docker Hub. (Cited from: "The image below is pulled from Docker Hub, and another attempt is made to create the container if the ubuntu image is not present in the victim machine.")
- Attacker uses the Docker Exec API to run commands within the created container. (Cited from: "Payloads are executed using a Docker Exec API.")
- The executed command uses
nsenter
targeting PID 1 (target 1
) with flags (--mount, --uts, --ipc, --net, --pid
) to break out of the container's namespace isolation and gain access equivalent to the host system. (Cited from: "The first part tries to escape the container by using the "nsenter" command to enter the specific namespaces of the target process with PID 1 (“target 1”)... indicating that it should enter the target's mount, UTS, IPC, network, and PID namespaces, effectively granting it similar capabilities as if it were running in the host system.")- BR-49: Namespace Execution Guard - This mechanism is specifically designed to block commands like
nsenter
from being used to enter container namespaces from the host, or in this case, usingnsenter
within a container with host PID access to manipulate host namespaces. It intercepts the underlyingsetns
syscall. - BR-47: Container Capability Control - This mechanism is applicable because using
nsenter
to manipulate namespaces typically requires theSYS_ADMIN
capability. If the container was prevented from having this capability (e.g., by BR-47 blocking privileged mode), thensenter
command would fail. - BR-41: Container Memory Namespace Isolation - This mechanism is applicable because it creates stronger isolation between namespaces, potentially interfering with or blocking the
nsenter
command's ability to switch between or manipulate namespaces effectively, particularly if memory access across namespaces is involved or attempted. - BR-68: Spaces-based Strong Isolation - This mechanism provides strong memory isolation between namespaces. While primarily focused on memory access, the robust isolation could potentially hinder or block the operations performed by
nsenter
when attempting to switch namespaces. - BR-90: Process Exec Deny - This mechanism could apply if
nsenter
itself (e.g.,/usr/bin/nsenter
) is added to the deny list policy, preventing its execution. - BR-88: Process Path Exec Allow - This mechanism could apply if
nsenter
is executed from a path (e.g., within the container's possibly modified filesystem) that is not on the execution allowlist.
- BR-49: Namespace Execution Guard - This mechanism is specifically designed to block commands like
- A Base64 encoded shell script is passed as the second part of the payload to
nsenter
. (Cited from: "The second part contains a Base64 encoded shell script.") - The decoded script first checks for and terminates existing instances of itself (
nsenter.bash.base64
) to prevent duplicates. (Cited from: "Step 1: Check and Prevent Duplicate Processes It checks for multiple running processes matching the pattern "nsenter.bash.base64" to avoid running similar processes simultaneously.") - The script creates a new bash script named
kubeupd
in/tmp
. (Cited from: "Step 2: Create a Bash Script It creates a bash script called "kubeupd" in the "/tmp" directory.")- BR-75: Critical Directory Write Protection - This mechanism could apply if
/tmp
were configured as a critical directory (though uncommon), blocking the write operation. - BR-65: Container Host Drift Prevention - This mechanism applies primarily to the execution of this script later, but the creation is the first step. It tracks files added post-boot and can block their execution if not done by an allow-listed process/container.
- BR-62: Linux/Host Drift Protection - This mechanism applies to the execution of this script if it was added outside a trusted package manager after escape to the host.
- BR-75: Critical Directory Write Protection - This mechanism could apply if
- Within
kubeupd
, the script sets an environment variableVEI
containing the public IP of the compromised Docker API (dck_<public IP of docker API>
). (Cited from: "This script sets the environment variable "VEI" to "dck_<public IP of docker API>." It is assumed that a customized payload has been generated based on the IP address identified in earlier stages.") kubeupd
also contains another Base64 encoded payload. (Cited from: "The script also includes another Base64 encoded bash payload.")- The inner Base64 payload within
kubeupd
is executed.- BR-88: Process Path Exec Allow - This mechanism is applicable because the script
/tmp/kubeupd
is being executed. If/tmp
is not an allowed execution path in the policy, BR-88 would block theexec()
call forbash /tmp/kubeupd
. - BR-65: Container Host Drift Prevention - This mechanism applies because a new script (
/tmp/kubeupd
), created after boot on the host filesystem (post-escape), is being executed. BR-65 blocks execution of files added post-boot unless created by allow-listed privileged containers or host processes. - BR-62: Linux/Host Drift Protection - This mechanism applies because a script (
/tmp/kubeupd
) added to the host filesystem outside of a trusted package manager is being executed. - BR-90: Process Exec Deny - This mechanism could apply if
bash
itself were added to the deny list, though this is generally impractical. - BR-54: Container Drift Protection (Binaries & Scripts) - This mechanism would apply if this execution step occurred inside the container before the escape, blocking the execution of a script not present in the original image. Since it happens post-escape, BR-62/BR-65 are more relevant.
- BR-88: Process Path Exec Allow - This mechanism is applicable because the script
- This inner script checks architecture (
x86_64
), creates/tmp
if missing, ensures/tmp
is executable (mount -o remount,exec /tmp
), and creates directories/tmp/.perfc
and/tmp/xdiag
. (Cited from: "The script will terminate if the architecture is not "x86_64."", "It initially checks for the presence of the "/tmp" directory and creates it if it does not exist. Then, it sets the "/tmp" mount as executable using the "exec" option. Subsequently, it creates ".perfc" and "xdiag" directories within the "/tmp" directory.")- BR-66: Host FS Mount Control - This mechanism is applicable because it intercepts mount system calls. The attempt to
remount
/tmp
with theexec
option could be blocked if the policy disallows modifications to mount options for critical filesystems or disallows theexec
flag on/tmp
. - BR-75: Critical Directory Write Protection - This mechanism could apply to the creation of
.perfc
andxdiag
if/tmp
were configured as a critical directory.
- BR-66: Host FS Mount Control - This mechanism is applicable because it intercepts mount system calls. The attempt to
- The script stores the
VEI
variable content into/tmp/.xdiag/vei
. (Cited from: "The environment variable $VEI, which contains "dck<publicip>", is included in "/tmp/.xdiag/vei."")- BR-75: Critical Directory Write Protection - This mechanism could apply if
/tmp
or/tmp/.xdiag
were configured as critical directories.
- BR-75: Critical Directory Write Protection - This mechanism could apply if
- It checks if a previous instance of the malware is running by looking for a PID file (
/tmp/.xdiag/p
) and verifying the process in/proc/
or checking for specific TCP ports (44870, 63582). (Cited from: "It confirms the presence of a malicious process by checking "/tmp/.xdiag/p," which should contain the PID of the malicious process. It verifies the existence of the same process by checking the "/proc/" directory. The secondary check looks for active TCP connections using ports 44870 or 63582.") - If no existing malware process is found, it downloads the main malicious binary from a C2 server (e.g.,
http://46.101.139[.]173/main/dist/aoip
), saving it as/tmp/httpd
(disguised as a PHP extension in the URL, saved with a legitimate-looking name). It uses a custom__curl
function ifcurl
orwget
are unavailable. (Cited from: "If it confirms that the process is not running, then it will download the malicious binary, which is disguised as a PHP extension, to avoid file extension-based detection.", "Downloading the binary file uses the custom __curl function if curl and wget are not in the system.", "It downloads the file in the “/tmp” directory with the “httpd” name to look like a legitimate name.", "http://46.101.139[.]173/main/dist/aoip")- BR-90: Process Exec Deny - This mechanism is applicable because it blocks execution based on process name suffixes. If the script attempts to execute
/usr/bin/curl
or/usr/bin/wget
, and the policy includes/curl
or/wget
(as default), their execution would be blocked. - BR-87: Process Socket Deny - This mechanism is applicable because it can prevent specified processes (like
bash
running the script, orcurl
/wget
if executed) from initiating outgoing network connections needed for the download. - BR-80: Tainted File Download Protection - This mechanism is specifically designed for this scenario. It monitors processes like
wget
orcurl
fetching code over the network and can block subsequent execution of that downloaded code. - BR-75: Critical Directory Write Protection - This mechanism could apply if
/tmp
were configured as a critical directory, preventing the binary from being saved there. - BR-88: Process Path Exec Allow - This mechanism applies to the execution of
curl
orwget
if they reside in a path not on the allowlist (less likely for standard tools, but possible). More relevant to the execution of the downloaded/tmp/httpd
in the next step. - BR-65: Container Host Drift Prevention - This mechanism applies to the execution of the downloaded file in the next step, as it tracks files added post-boot.
- BR-62: Linux/Host Drift Protection - This mechanism applies to the execution of the downloaded file in the next step, as it tracks files added outside trusted package managers.
- BR-90: Process Exec Deny - This mechanism is applicable because it blocks execution based on process name suffixes. If the script attempts to execute
- After verifying the download (file existence and size check), it kills any existing
perfctl
processes, sets executable permissions on the downloaded binary (/tmp/httpd
), updates the PATH, and executes the binary (KRI=kr httpd
) in the background. (Cited from: "If the downloaded file exists and its size matches a specific value (e.g., 9301499), it triggers more actions. These actions include killing processes (perfctl), setting permissions, updating the PATH environment variable, and executing a command (KRI=kr httpd) in the background.")- BR-65: Container Host Drift Prevention - This mechanism is highly applicable. It detects that
/tmp/httpd
is a file added/modified on the host filesystem after boot and was not created by an allow-listed process/container, and blocks its execution. - BR-62: Linux/Host Drift Protection - This mechanism is highly applicable. It detects that
/tmp/httpd
was added to the host filesystem outside of a trusted package manager and blocks its execution. - BR-88: Process Path Exec Allow - This mechanism is highly applicable. If
/tmp
is not included in the allowlist of executable paths, the execution of/tmp/httpd
will be blocked. - BR-54: Container Drift Protection (Binaries & Scripts) - This mechanism would apply if this execution occurred within the container before escape, blocking a binary not in the original image. Since it's post-escape on the host, BR-62/BR-65 are the primary mitigations.
- BR-55: Reverse Shell Protection - This mechanism could apply if the executed
/tmp/httpd
binary attempts to establish a reverse shell by binding shell I/O to a network socket. - BR-90: Process Exec Deny - This mechanism could apply if the name
httpd
itself (or a pattern matching it) was added to the deny list, although the default deny list focuses onnc
,wget
,curl
. - BR-87: Process Socket Deny - This mechanism could apply if the policy denies network socket access for the process named
httpd
(or the process that executed it), preventing its C2 communication.
- BR-65: Container Host Drift Prevention - This mechanism is highly applicable. It detects that
- The script establishes persistence: if
systemd
is active, it creates a systemd service; otherwise, it creates a cron job. (Cited from: "Step 4: Engage a Persistence Strategy To remain active, the malware uses a persistence strategy. If systemd runs as non-offline, it creates a systemd service using "multi-user.target." Otherwise, it resorts to creating a cron job")- BR-75: Critical Directory Write Protection - This mechanism is applicable if the directories where systemd service files (
/etc/systemd/system/
,/usr/lib/systemd/system/
) or cron jobs (/etc/cron.d/
,/var/spool/cron/
) are stored are configured as critical and write-protected. - BR-65: Container Host Drift Prevention - This mechanism applies if the persistence mechanism involves executing a script or binary (
/tmp/httpd
or/tmp/kubeupd
) that was added post-boot and is covered by drift protection. It blocks the execution triggered by systemd or cron. - BR-62: Linux/Host Drift Protection - This mechanism applies if the persistence mechanism involves executing a script or binary added outside a trusted package manager. It blocks the execution triggered by systemd or cron.
- BR-88: Process Path Exec Allow - This mechanism applies if the persistence mechanism executes a script or binary from a path (like
/tmp
) that is not on the allowlist.
- BR-75: Critical Directory Write Protection - This mechanism is applicable if the directories where systemd service files (
- The script includes a fallback mechanism (
Fallback
function) involving replacing/bin/sh
with a modified version (/bin/kkbush
) to potentially bypass detection and maintain access, later restoring the original. (Cited from: "Fallback: It sets up a persistent backdoor by replacing the original "/bin/sh" shell with a modified version that enables privilege escalation and execution of any command. It then duplicates the original "sh" file as the "kkbush" and "kbush" binaries and later restores it during the cleanup process.", "Restore_sh: It replaces the "/bin/sh" file with "/bin/kkbush" to bypass the detection (T1036.005).")- BR-75: Critical Directory Write Protection - This mechanism is highly applicable if
/bin
is configured as a critical directory. It would block the attempt to overwrite/bin/sh
. - BR-65: Container Host Drift Prevention - This mechanism applies to the execution of the replaced
/bin/sh
or the newkkbush
binary, as these represent modifications or additions to the host filesystem post-boot. - BR-62: Linux/Host Drift Protection - This mechanism applies to the execution of the replaced
/bin/sh
or the newkkbush
binary, as these modifications were made outside a trusted package manager. - BR-88: Process Path Exec Allow - This mechanism could apply if the modified shell or
kkbush
were moved to a non-allowed path before execution, or potentially if modification of files in allowed paths triggers scrutiny (though BR-88 focuses on exec path). - BR-54: Container Drift Protection (Binaries & Scripts) - This mechanism would apply if this file replacement occurred within the container before the escape.
- BR-75: Critical Directory Write Protection - This mechanism is highly applicable if