Initial access Execution Persistence Privilege escalation Defense evasion Credential access Discovery Lateral movement Collection Impact
Using Cloud Exec into Container Backdoor Container Privileged Container Clear Container Logs List K8s secrets Access the K8s API server Access cloud resources Images from a private repository Data Destruction
Compromised images in registry bash/cmd in container Writable hostPath mount Cluster-admin binding Delete k8s events Mount service principal Access Kubelet API Container service account Ressource hijacking
Kubeconfig file New container Kubernetes CronJob hostPath mount Pod / container name similarity Access container service account Network mapping Cluster internal networking Denial of Service
Application vulnerability Application exploit (RCE) Malicious admission controller Access cloud resources Connect from proxy server Applications credentials in configuration files Access Kubernetes dashboard Applications credentials in configuration files
Exposed sensitive interfaces SSH server running in inside container Disable Namespacing Access managed identity credentials Instance metadata API Writable volume mounts on the host
Sidecar injection Malicious admission controller CoreDNS poisoning
ARP poisoning and IP spoofing

Kubeconfig file

The kubeconfig file, also used by kubectl, contains details about Kubernetes clusters including their location and credentials. If the cluster is hosted as a cloud service (such as AKS or GKE), this file is downloaded to the client via cloud commands (e.g., “az aks get-credential” for AKS or “gcloud container clusters get-credentials” for GKE).

If attackers get access to this file, for instance via a compromised client, they can use it for accessing the clusters.

Example

Get a kubeconfig file from somewhere.

$ cat ~/.kube/config

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: LS0tLS1CRUdJ...VEUtLS0tLQo=
    server: https://k8s.example.com:63958
  name: my-k8s-cluster
contexts:
- context:
    cluster: my-k8s-cluster
    user: admin@my-k8s-cluster
  name: my-k8s-cluster
current-context: my-k8s-cluster
kind: Config
preferences: {}
users:
- name: admin@my-k8s-cluster
  user:
    client-certificate-data: LS0tLS1CRUdJ...QVRFLS0tLS0K
    client-key-data: LS0tLS1CRUdJ...RVktLS0tLQo=

Use the kubeconfig file (in our case called my-kubeconfig and located in the current directory).

$ kubectl --kubeconfig ./my-kubeconfig get pods -n kube-system
NAME                                      READY   STATUS      RESTARTS   AGE
local-path-provisioner-7b7dc8d6f5-qctrl   1/1     Running     0          7m23s
coredns-b96499967-lgdhf                   1/1     Running     0          7m23s
helm-install-traefik-crd-vt9np            0/1     Completed   0          7m23s
helm-install-traefik-hc7vb                0/1     Completed   1          7m23s
svclb-traefik-aa669165-h8v6r              2/2     Running     0          7m5s
metrics-server-668d979685-knbhs           1/1     Running     0          7m23s
traefik-7cd4fcff68-4t49p                  1/1     Running     0          7m5s

To avoid the need for --kubeconfig or storing the kubeconfig file in it’s default location (~/.kube/config), we can use the KUBECONFIG environment variable.

$ kubectl get pods -n kube-system
The connection to the server localhost:8080 was refused - did you specify the right host or port?

$ export KUBECONFIG=./my-kubeconfig # ideally use the absolute path instead
$ kubectl get pods -n kube-system
NAME                                      READY   STATUS      RESTARTS   AGE
local-path-provisioner-7b7dc8d6f5-qctrl   1/1     Running     0          7m23s
coredns-b96499967-lgdhf                   1/1     Running     0          7m23s
helm-install-traefik-crd-vt9np            0/1     Completed   0          7m23s
helm-install-traefik-hc7vb                0/1     Completed   1          7m23s
svclb-traefik-aa669165-h8v6r              2/2     Running     0          7m5s
metrics-server-668d979685-knbhs           1/1     Running     0          7m23s
traefik-7cd4fcff68-4t49p                  1/1     Running     0          7m5s

References