☸️ Ломаем и чиним Kubernetes |

☸️ Ломаем и чиним Kubernetes

Мануал

Kubernetes – это отличная платформа для управления контейнерами, которая в последнее время демонстрирует прорыв как в плане функциональности, так и в плане безопасности и отказоустойчивости.

Специалисты утверждают, что архитектура Kubernetes позволяет ей легко переживать различные сбои и оставаться активной несмотря ни на что, что делает ее отличным вариантом для проведения пентестов.

Далее мы рассмотрим как выполнить несколько хакерских атак на Kubernetes, включая разрушение кластера, удаление сертификата и подключение ноды, и все это без простоя запускаемых сервисов.

Прежде чем продолжить, мы, как обычно, напоминаем, что эта статья подготовлена исключительно в информационных целях и не должна восприниматься как призыв к действию.

Чтобы начать, давайте вспомним, что основная панель управления Kubernetes состоит из нескольких компонентов:

  • etcd: Используется в качестве базы данных
  • kube-apiserver: API и сердце кластера
  • kube-controller-manager: Для развертывания на ресурсах Kubernetes
  • kube-scheduler: Главный планировщик
  • kubelets: Для запуска контейнеров непосредственно на хостах

Каждый из этих компонентов защищен набором TLS, клиентских и серверных сертификатов, целью которых является аутентификация и авторизация компонентов между собой.

Эти ресурсы нигде не хранятся в базе данных Kubernetes, за исключением некоторых случаев, а представлены в виде обычных файлов:

# tree /etc/kubernetes/pki/ /etc/kubernetes/pki/ ├── apiserver.crt ├── apiserver-etcd-client.crt ├── apiserver-etcd-client.key ├── apiserver.key ├── apiserver-kubelet-client.crt ├── apiserver-kubelet-client.key ├── ca.crt ├── ca.key ├── CTNCA.pem ├── etcd │ ├── ca.crt │ ├── ca.key │ ├── healthcheck-client.crt │ ├── healthcheck-client.key │ ├── peer.crt │ ├── peer.key │ ├── server.crt │ └── server.key ├── front-proxy-ca.crt ├── front-proxy-ca.key ├── front-proxy-client.crt ├── front-proxy-client.key ├── sa.key └── sa.pub

Сами компоненты описываются и запускаются на мастерах в виде статических подов из каталога /etc/kubernetes/manifests/.

Самое главное – знать, как из всего этого сделать функциональный кластер; представим, что упомянутые выше компоненты Kubernetes каким-то образом взаимодействуют друг с другом.

Базовая схема выглядит следующим образом:

Для общения им нужны TLS-сертификаты, которые, в принципе, можно вынести на отдельный уровень абстракции и полностью положиться на свой инструмент распространения, будь то kubeadm, kubespray или что-то еще, упоминают эксперты по пентестингу.

В данном примере мы рассмотрим kubeadm, поскольку это наиболее распространенный инструмент развертывания Kubernetes и часто используется в составе других решений.

Предположим, что у нас уже есть кластер.

Начнем с самого интересного:

rm -rf /etc/kubernetes/

У мастер нод этот каталог содержит:

  • Набор сертификатов и CA для etcd (c/etc/kubernetes/pki/etcd)
  • Набор сертификатов и CA для Kubernetes (c/etc/kubernetes/pki)
  • Kubeconfig для cluster-admin, kube-controller-manager, kube-Scheduler и kubelet (каждый также имеет сертификат CA в base64-кодировке для нашего кластера /etc/kubernetes/*.conf)
  • Набор статических манифестов для etcd, kube-apiserver, kube-Scheduler и kube-controller-manager (c/etc/kubernetes/manifests)

Предположим, мы потеряли все и сразу.

Исправление проблем control plane

Чтобы избежать путаницы, исследователи рекомендуют убедиться, что все наши поды control plane также остановлены:

crictl rm `crictl ps -aq`

Следует помнить, что kubeadm по умолчанию не перезаписывает существующие сертификаты и kubeconfigs, поэтому для их повторного выпуска необходимо сначала вручную удалить их.

Начнем с восстановления etcd, потому что если у нас есть кворум (3 или более мастер-нод), то кластер etcd не запустится без присутствия большинства из них.

kubeadm init phase certs etcd-ca

Приведенная выше команда создаст новый CA для нашего кластера etcd.

Поскольку все остальные сертификаты должны быть подписаны им, мы скопируем его вместе с закрытым ключом на остальные мастер-ноды:

/etc/kubernetes/pki/etcd/ca.{key,crt}

Теперь давайте перегенерируем остальные сертификаты etcd и статические манифесты на всех нодах в control plane:

kubeadm init phase certs etcd-healthcheck-client
kubeadm init phase certs etcd-peer
kubeadm init phase certs etcd-server
kubeadm init phase etcd local
На этом этапе у нас уже должен работать кластер etcd:
# crictl ps
CONTAINER ID        IMAGE               CREATED             STATE               NAME                ATTEMPT             POD ID
ac82b4ed5d83a       0369cf4303ffd       2 seconds ago       Running             etcd                0                   bc8b4d568751b
Теперь сделаем то же самое, но для Kubernetes, на одной из мастер-нод выполним:
kubeadm init phase certs all
kubeadm init phase kubeconfig all
kubeadm init phase control-plane all
cp -f /etc/kubernetes/admin.conf ~/.kube/config
Приведенные выше команды сгенерируют все SSL-сертификаты для нашего кластера Kubernetes, а также статистику манифестов и kubeconfigs для сервисов Kubernetes.
Если вы используете kubeadm для присоединения kubeletов, вам также необходимо обновить конфигурацию информации о кластере в пространстве имен kube-public, которая все еще содержит хэш вашего старого CA.
kubeadm init phase bootstrap-token
Поскольку все сертификаты других экземпляров также должны быть подписаны CA, скопируйте их на другие мастер ноды и повторите описанные выше команды на каждом из них, рекомендуют эксперты.
/etc/kubernetes/pki/{ca,front-proxy-ca}.{key,crt}
/etc/kubernetes/pki/sa.{key,pub} 
В качестве альтернативы ручному копированию сертификатов теперь можно использовать интерфейс Kubernetes, например, следующую команду:
kubeadm init phase upload-certs --upload-certs
Затем сертификаты будут зашифрованы и загружены в Kubernetes на 2 часа, после чего вы сможете присоединиться к мастерам следующим образом:
kubeadm join phase control-plane-prepare all kubernetes-apiserver:6443 --control-plane --token cs0etm.ua7fbmwuf1jz946l     --discovery-token-ca-cert-hash sha256:555f6ececd4721fed0269d27a5c7f1c6d7ef4614157a18e56ed9a1fd031a3ab8 --certificate-key 385655ee0ab98d2441ba8038b4e8d03184df1806733eac131511891d1096be73
kubeadm join phase control-plane-join all
Стоит отметить, что в Kubernetes API есть еще одна конфигурация, которая хранит сертификат CA для клиента front proxy, используемого для аутентификации запросов apiserver к вебхуков и другим сервисам уровня агрегации.
К счастью, kube-apiserver обновляет его автоматически.
Однако вы можете захотеть вручную очистить его от старых сертификатов:
kubectl get cm -n kube-system extension-apiserver-authentication -o yaml
В любом случае, на данном этапе у нас уже есть полностью функционирующий control plane.

Чиним воркер ноды

Эта команда выведет список всех нод  кластера, хотя теперь все они будут находиться в состоянии NotReady:

kubectl get node

Это происходит потому, что они все еще используют старые сертификаты и ждут запросов от сервера, подписанных старым CA.

Чтобы обойти эту проблему, мы воспользуемся kubeadm:

systemctl stop kubelet
rm -rf /var/lib/kubelet/pki/ /etc/kubernetes/kubelet.conf
kubeadm init phase kubeconfig kubelet
kubeadm init phase kubelet-start
Затем для воркеров мы сгенерируем новый токен:
kubeadm token create --print-join-command
И на каждом из них мы выполняем:
systemctl stop kubelet
rm -rf /var/lib/kubelet/pki/ /etc/kubernetes/pki/ /etc/kubernetes/kubelet.conf
kubeadm join phase kubelet-start kubernetes-apiserver:6443  --token cs0etm.ua7fbmwuf1jz946l     --discovery-token-ca-cert-hash sha256:555f6ececd4721fed0269d27a5c7f1c6d7ef4614157a18e56ed9a1fd031a3ab8

Внимание: /etc/kubernetes/pki/ не обязательно удалять в директории мастер нод, так как в ней содержатся все необходимые сертификаты, говорят эксперты.

Предыдущая процедура переподключит все ваши kubletы к кластеру, не затрагивая уже запущенные на них контейнеры.

Однако если у вас много нод в кластере и вы делаете это одновременно, может возникнуть ситуация, когда Controller-Manager начнет пересоздавать контейнеры с нодами NotReady и попытается запустить их на активных нодах кластера.

Чтобы избежать этого, мы можем временно остановить его на мастерах:

rm /etc/kubernetes/manifests/kube-controller-manager.yaml
crictl rmp `crictl ps --name kube-controller-manager -q`

Последняя команда нужна только для того, чтобы убедиться, что кController-Manager  на самом деле не запущен.

Когда все ноды кластера подключены, мы можем сгенерировать статический манифест для бэка.

Для этого нужно будет выполнить:

kubeadm init phase control-plane controller-manager
Обратите внимание, что это необходимо сделать на этапе, когда вы уже сгенерировали токен для присоединения; в противном случае операция подключения завершится аварийно при попытке прочитать токен cluster-info.

Если kubelet настроен на получение сертификата, подписанного вашим CA (опциональный сервер TLSBootstrap: true), вам также потребуется подтвердить csr ваших kubelet:

kubectl get csr
kubectl certificate approve <csr>

Восстановление Service Accounts

Есть еще один момент.

Поскольку мы потеряли /etc/kubernetes/pki/sa.key, эксперты отмечают, что это тот же ключ, которым были подписаны jwt-токены для всех наших ServiceAccounts, поэтому нам нужно заново создать токены для каждого из них.

Это можно сделать, просто удалив поле token из всех секретов kubernetes.io/service-account-token:

kubectl get secret --all-namespaces | awk '/kubernetes.io\/service-account-token/ { print "kubectl patch secret -n " $1 " " $2 " -p {\\\"data\\\":{\\\"token\\\":null}}"}' | sh –x
После этого kube-controller-manager будет автоматически генерировать новые токены, подписанные новым ключом.
К сожалению, не все микросервисы могут перечитывать токен на лету, и вам, скорее всего, придется вручную перезапускать контейнеры, в которых они используются:
kubectl get pod --field-selector 'spec.serviceAccountName!=default' --no-headers --all-namespaces | awk '{print "kubectl delete pod -n " $1 " " $2 " --wait=false --grace-period=0"}'

Например, эта команда сгенерирует список команд для удаления всех подов, использующих нестандартный сервис аккаунт.

Я рекомендую начать с неймспеса kube system.

У вас установлены kube-proxy и плагин CNI, которые жизненно важны для настройки взаимодействия ваших микросервисов.

см. также:

Пожалуйста, не спамьте и никого не оскорбляйте. Это поле для комментариев, а не спамбокс. Рекламные ссылки не индексируются!
Добавить комментарий