Skip to content
Sedat Özdemir
Writing

cloud-native

The Orchestrator or an Insider Trojan? Invisible Dangers in the Kubernetes World

Security has shifted from physical firewalls to the orchestration layer. Let's dive into the dark corners of Kubernetes security—from API Server leaks to RBAC misconfigurations—and talk about how to keep the cluster safe.

Sedat Özdemir
· 3 dk read

Until yesterday, we used to say, 'Hey, we’re behind a firewall; if SSH isn't open on the server, we’re good.' Then containers arrived, and suddenly we found ourselves managing massive Kubernetes clusters. The trend has evolved from the physical security of the server to how 'smartly' the orchestration layer managing those servers is configured. We used to argue about 8-character passwords; now we're wrestling with much more painful questions like 'Should I expose the K8s API Server to the internet?'

Hey friends, I'm Sedat. Today, we’re going to dive into the dark corners of the cloud-native world: Kubernetes security.

API Server: The Main Gate of the Fortress

When people think of Kubernetes, the first thing that comes to mind is the kubectl command. But behind that command, there's actually a massive REST API running. If an attacker gains access to your API Server, they can control everything within the cluster. Often, in environments like 'testCompany', we see the API Server left accessible via a public IP just to gain some speed. This is no different from leaving the keys in the door.

As a Red Teamer, one of the first things I check is the anonymous-auth setting. If this is set to true (which was the default in older versions), even an unauthorized user can gather information about the cluster.

# Defanged check command
curl -k https://127.0.0.1:6443/livez
# If you get a 200 OK from here, the door is at least 'there'.

Defense Prescription: Never expose the API Server to the public internet. Only allow access from specific IPs (VPN or Jumpbox) and ensure anonymous-auth=false is set.

RBAC: Privilege Poisoning

Configuring RBAC (Role-Based Access Control) is a total headache, I admit. That's why people usually just want it to 'just work' and end up granting cluster-admin privileges to every ServiceAccount. This is our favorite kind of misconfiguration.

When we compromise a pod, the first thing we do is check the token of the ServiceAccount that pod is tied to. If that token allows cluster-level operations, it’s game over.

A Bad Example (Over-privileged Role):

# THIS IS AN ANTIPATTERN - NEVER DO THIS
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: dev-service-account-binding
subjects:
- kind: ServiceAccount
  name: default
  namespace: dev-app
roleRef:
  kind: ClusterRole
  name: cluster-admin # Disaster scenario!
  apiGroup: rbac.authorization.k8s.io

Instead, apply the principle of Least Privilege. Define only the 'verbs' (get, list, watch) needed, and only for the specific namespace required.

Pod Security: The Spy Within

Containers are often thought to be isolated, but they all share the same kernel. Running a pod with privileged: true means that pod can access devices on the host machine. This is the shortest ticket to becoming 'root'.

Once an attacker is inside a pod, the first thing they’ll try is to jump into the host namespace using tools like nsenter.

Related posts