In a previous article, we described how the usage of namespaces in Kubernetes significantly simplifies the management of a Kubernetes cluster. However, managing multiple microservices on the same cluster comes with a security cost when not planned correctly.
A common misconception around namespaces is that they are truly separated. However, it is more likely to think of it as a police tape—you know it is there, but it is fairly easy to bypass it.
In real life, this translates to a scenario when a newly created service ignores namespace segmentation by default, thus being exposed to other microservices running in the same cluster.
In this article, we will review several security risks when managing microservices with different security requirements (e.g. frontend and database) on the same cluster.
Is Kubernetes insecure by default?
While Kubernetes was originally designed without security tenancy and segmentation, it does have two important security mechanisms. The first one is RBAC (Role-Based Access Control). This mechanism matches users and service accounts to their allowed (or forbidden) actions on components, and basically manages the permissions on the cluster.
The second mechanism is Network Policy, which essentially acts as a firewall that manages traffic mostly inside the cluster. This mechanism is unlike a traditional enterprise firewall that manages traffic in and out of the perimeter network.
When talking about container segmentation within nodes, we should start by explaining the Linux kernel namespaces concept, as containers use this kind of segmentation between one another. Although the name is similar, it is very different from Kubernetes namespaces.
A Linux kernel namespace is considered fairly secure, as it isolates global system resources between independent processes of the system. Some of those resources may be shared among different Linux kernel namespaces, such as process IDs, hostnames, file names, etc., while some may be hidden and separated, like privileges and user identifications.
Regardless of the Kubernetes namespace, a new Linux kernel namespace is created by the container runtime for each new container.
Does it mean all containers are separated on the nodes?
It does, but the Achilles' heel of the Linux kernel namespaces is the shared Kubernetes resources, including the API server, kube-proxy, container runtime daemon, and the kubelet process, which is responsible for managing all the physical resources on the node. This enables attackers to gain access to additional containers on the same node, ultimately leading to an extraction of sensitive information about the node and its configurations.
Kubernetes has some major security holes when using its default configurations—for example, the kubelet and its API being a centralized point on the node. This is a classic scenario for an attacker to manipulate in order to retrieve information about the whole node and its configuration. But in reality, the vast majority of security issues are due to misconfigurations by users—for example, leveraging the Writable hostPath mount technique, as part of the Persistence tactic we covered in our Kubernetes attack matrix blog series.
Network is discoverable for all pods
The default DNS service of the cluster is kube-dns, and it assigns by design a DNS entry to pods and services with known patterns. The kube-dns was not meant to restrict DNS entries from specific clients or throttle requests to block brute-force clients. Any resource that exists on the cluster can get any DNS record from it.
For every pod connected to a service, there is a similar DNS record with the pod IP as a subdomain. These DNS records are shared among all pods in the cluster, and can be easily exploited by executing numerous reverse nslookup commands. This is a powerful way to discover a lot of information about the cluster such as the size, existing deployments (which are usually deployed with indicative names like nginx, mysql, etc.). Another security issue is the fact that pods are accessible via their shared DNS records, unless guarded by a well-defined network policy.
Container privileges escalation
Apart from getting into Kubernetes components that exist in different namespaces, an attacker can gain access even to node host itself, thus having control of all the compute resources and sensitive data. These vulnerabilities can be leveraged for crypto-mining, and even access to private information stored in nodes and containers.
Another example was discovered by Felix Wilhelm from the Google Security Team, who tweeted about a “quick and dirty way to get out of a privileged k8s pod.” Although this breach often occurs on non-default privileged containers, teams should always pay attention to secured containers that are in use as well. We have recently reviewed the Privilege Escalation attack vector in this article.
Namespaces are a great way to organize your microservices on the cluster. Holding different microservices, such as frontend and backend or client and database, on the same cluster can make the overall application or service more efficient and easier to maintain at the cost of security when not handled correctly.
Alcide by Rapid7 provides essential, security-oriented capabilities, including microservices firewall at scale, enhanced Kubernetes and cloud-native security policies, image scanning, and vulnerability management, all powered by a behavioral-based anomaly detection engine.
Interested to learn more? Speak with an expert!