IL-0068 Aqua Security · 2023-04-21 (published)kubernetessecurityaws
The attacker came in through the API server, which let anonymous users make privileged requests. After listing secrets and looking around kube-system, the attacker checked whether the cluster was already infected, then tried to delete deployments that probably belonged to older or competing mining campaigns, to free CPU and avoid notice.
For persistence the attacker used RBAC (role-based access control): a new ClusterRole with near admin privileges, not tied to any namespace; a ServiceAccount kube-controller in kube-system; and a ClusterRoleBinding system:controller:kube-controller joining the two. With that binding the attacker keeps access even after anonymous access is turned off. One API request then created a DaemonSet that put the mining container on every node. The attacker also tried the AWS access keys found in the cluster to reach further into the cloud account.
Aqua named the attack RBAC Buster. The image had been pulled 14,399 times in the five months since it was uploaded, and Aqua found evidence of the same attacker on another 60 exposed clusters. Each of the image's three tags contained a binary kube-controller (MD5 2833c82055bf2d29c65cd9cf6684449a) that VirusTotal detects as a cryptominer, and the wallet in its configuration had already received 5 XMR.
Aqua's research team Nautilus recorded the attack on one of its Kubernetes honeypots. What appeared in the cluster was a DaemonSet running the image kuberntesio/kube-controller:1.0.1 from Docker Hub on every node, using the nodes' CPU to mine Monero.
The names were chosen to look like part of Kubernetes: a ServiceAccount kube-controller in the kube-system namespace, a ClusterRole with near admin privileges, and a ClusterRoleBinding named system:controller:kube-controller. The image name kuberntesio/kube-controller is a typosquat of the legitimate kubernetesio account and imitates the control plane image kube-controller-manager. In audit logs and workload lists these look like normal components, unlike a new user bound to cluster-admin, which might raise an alarm.
Before that, the attacker listed secrets and the contents of kube-system, checked for an existing deployment named kube-controller, and tried to delete deployments in other namespaces, among them kube-secure-fhgxtsjh, kube-secure-fhgxt, api-proxy and worker-deployment. Later the same day, AWS access keys planted in the honeypot sent a beacon: the attacker had tried to use them against the cloud account.
Symptom ? Unauthorised access or a foreign workloadResources deleted
Root cause ? Configuration change
Aqua recorded the attacker's API requests on its honeypot; planted AWS access keys raised a beacon when the attacker tried to use them.
–
–
Fixing an exposed API server is not enough once an attacker has been in: a ClusterRoleBinding to an attacker-created ServiceAccount keeps working after anonymous access is closed. Attackers name these objects and images after real Kubernetes components so they blend into the API audit logs and pass for legitimate deployments. Aqua recommends scanning clusters for vulnerabilities, exposed secrets and misconfigurations with a tool such as Trivy.
same root cause · shared Kubernetes API server
same root cause · shared Kubernetes API server
same root cause · shared Kubernetes API server
same root cause · shared Kubernetes API server
same root cause · shared Kubernetes API server