curl -k -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://127.0.0.1:6443/api/v1/namespaces/default/secrets
If this command successfully returns a response from inside a pod, well, GG; you’ve basically left the keys to the kingdom under the doormat. Welcome to the world of Kubernetes (K8s), my friend. It’s a place where everything moves fast and scales hard, but it’s also a wild west where a single line in a YAML file can turn your entire infrastructure 'public.'
Today, we’re going to talk about those critical configuration errors we frequently run into during our operations at testCompany. From a Red Team perspective, these make our mouths water, but on the defense side, they’re the stuff of nightmares. Grab your coffee, because plenty of folks have paid a heavy price in the field for trusting 'default' settings.
1. RBAC: Handing Out the Keys to Everyone
Role-Based Access Control (RBAC) is the heart of K8s security. But how does it usually go down? "Hey, the devs are getting errors, let’s just give this ServiceAccount Cluster-Admin so they can get things moving." In that exact moment, you’re dropping a live grenade right in the middle of your cluster.
When an attacker compromises a pod, the first thing they do is check the /var/run/secrets/kubernetes.io/serviceaccount/token file. If this token is linked to an overly permissive ClusterRoleBinding, the attacker is now your cluster admin. Period.
The Bad Scenario (Example):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-everything-everywhere
subjects:
- kind: ServiceAccount
name: default
namespace: app-namespace
roleRef:
kind: ClusterRole
name: view # Or even worse, 'cluster-admin'
apiGroup: rbac.authorization.k8s.io
The danger here is the broad permissions granted to the default service account.
What to do?
- Least Privilege: Define a specific
ServiceAccountfor each pod with only the permissions it absolutely needs. - AutomountServiceAccountToken: If your pod doesn't need to talk to the K8s API, set
automountServiceAccountToken: false. Why mount the token inside if you don't have to?
2. Privileged Containers: The Shortcut to the Host System
Running a container with privileged: true means the root user inside that container has almost the same privileges as the root user on the host. If an attacker gains access to this pod, escaping the container takes mere seconds.
spec:
containers:
- name: insecure-container
image: example.com/app:latest
securityContext:
privileged: true # This is a suicide note
From here, an attacker can simply run mount /dev/sda1 /mnt/host to mount the host machine's disk and use chroot to become the master of the host. The K8s layer is effectively bypassed; they are now directly inside your physical or virtual server.
The Solution:
- Use tools like Pod Security Admissions (PSA) or Gatekeeper to completely ban the use of
privilegedcontainers. If a container really needs specific hardware access, usecapabilitiesto grant only the specific permission required, rather than giving it the whole kingdom.
