Что, если… забыть про безопасность кластера k8s? |
||
МЕНЮ Главная страница Поиск Регистрация на сайте Помощь проекту Архив новостей ТЕМЫ Новости ИИ Голосовой помощник Разработка ИИГородские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Искусственный интеллект Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Нейронные сети начинающим Психология ИИ Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Творчество ИИ Техническое зрение Чат-боты Авторизация |
2022-08-08 21:55 Глава 1. Предпосылки Я думаю, многие слышали про громкий инцидент, произошедший с Tesla в 2018 году, когда группа хакеров через консоль Kubernetes смогла получить доступ к аккаунту. После получения доступа ребята изрядно повеселились, настроив майнер в облачном сервисе Amazon Web Services. У многих людей сразу же возникнут закономерные вопросы “А как они это сделали?” и “Почему многоуважаемые ИБ данной компании не подумали о потенциальной дыре в безопасности?”. Как правило, при разработке любого продукта могут быть лишь две причины возникновения уязвимостей. Первая причина - человеческий фактор. Ведь кто из нас не забывал что-либо в ходе кропотливой работы над проектом или же не откладывал в бэклог решение “не самых срочных вопросов..?”. Вторая причина - отсутствие необходимых компетенций в той или иной области. И здесь возникает логичный вопрос: “ DevSecOps - это философия, подразумевающая интеграцию принципов безопасности на всех стадиях жизни приложения. От его разработки и сборки, до его эксплуатации непосредственно в инфраструктуре. И на этом этапе начинается прекрасная повесть “Чем дальше в лес, тем больше дров”. В рамках своего рассказа я не буду стремиться описать сразу все направления этой многогранной философии, а уделю внимание лишь тому, что меня особенно заинтересовало. Итак, моделируем ситуацию. К вам приходит проект, в рамках которого клиент озвучивает требования о полностью безопасной и стабильной рабочей инфраструктуре k8s. Вы с радостью начинаете искать свои завалявшиеся Terraform-модули для раскатки куба в том или ином облаке, но в какой-то момент становится понятно, что клиент не готов создавать новую инфраструктуру, а хочет оптимизировать текущую. Нет более страшной работы для DevOps-инженера, чем работать с тем, что создавалось не тобой. Глава 2. С луком и стрелой на железного зверя Что такое Kube-Hunter и с чем его едят? Фактически это утилита, запускающая определенные тесты, которые пытаются проверить на наличие дыр в безопасности инфраструктуры вашего куба. Утилита имеет 2 варианта запуска, как в контейнере docker локально на хосте, так и в виде poda в k8s, а также два режима тестирования: пассивный и активный. Если с пассивным, я уверен, вопросов ни у кого не возникает, то с активным сложнее - во время тестирования он использует найденные уязвимости для поиска других уязвимостей, и потенциально может внести изменения в инфраструктуру. Так что поосторожней с запуском на prod. Хотя на личном опыте могу сказать, что сколько бы ни тестировал этот инструмент, я не смог обнаружить каких-либо изменений в инфраструктуре кластера. Произведем запуск kube-hunter в кластере: apiVersion: batch/v1 kind: Job metadata: name: kube-hunter spec: template: metadata: labels: app: kube-hunter spec: containers: - name: kube-hunter image: aquasec/kube-hunter:latest command: ["kube-hunter"] args: ["--pod", "--enable-cve-hunting", "--statistics"] restartPolicy: Never Делаем apply нашей job и через пару минут смотрим в отработанном поде логи. Результат, который я получил, имел примерно следующий вывод:
А также итоговая статистика о всех проверках, которые были произведены и об их результатах: Первая же найденная уязвимость гласила: “CAP_NET_RAW включен по умолчанию для модулей. Если злоумышленнику удастся скомпрометировать под, он потенциально может воспользоваться этой возможностью для выполнения сетевых атак на другие поды, работающие на том же узле”. Отлично, общая суть понятна. Но, как у любого инженера, у меня сразу возникает ряд вопросов. Как то:
Давайте же разберем самую интересную и наглядную, по моему мнению, уязвимость. Глава 3. Ответы на вопросы, порождающие ещё больше вопросов После недолгих поисков я нашел следующую информацию. CAP_NET_RAW — это разрешающий параметр по умолчанию в Kubernetes, разрешающий трафик ICMP между контейнерами, и предоставляющий приложению возможность создавать необработанные пакеты. В руках злоумышленника CAP_NET_RAW может позволить использовать широкий спектр сетевых эксплойтов внутри кластера. Чтобы понять, можно ли отключить данный параметр, нужно понимать, как работает сеть куба. Это также позволит понять, как злоумышленник может воспользоваться данной настройкой. Сетевая архитектура Kubernetes Подключение подов, работающих на одном узле или на разных узлах, не является тривиальной задачей. Для обеспечения этого соединения существует полная инфраструктура, которая, в основном, опирается на сетевые пространства имен, сетевые устройства Linux, таблицы маршрутизации и оверлейные сети. Рисунок выше описывает абстракцию сетевой структуры на одном узле. Каждый под находится в отдельном сетевом пространстве имен, и существуют сетевые устройства, которые создают связь между различными подами и корневым пространством имен. Это уровень, который управляет трафиком данных внутри и снаружи узла. Пространство имен корневой сети содержит несколько компонентов. Первый — это под сетевого плагина, который работает (в отличие от большинства других модулей) в корневом сетевом пространстве имен с возможностями NET_ADMIN. Это позволяет реализовать различные конфигурации на узле. Еще одним компонентом, входящим в инфраструктуру Kubernetes, является под kube-proxy, который отвечает за сетевые свойства, такие как правила iptables, при создании службы в кластере. Помимо этих компонентов есть четыре основных сетевых устройства Linux. Компоненты veth (виртуальный ethernet), о котором я расскажу подробнее позже, и компоненты моста, которые отвечают за подключение подов к сетевому пространству узла, чтобы пакеты могли проходить между подами на одном узле или передаваться другим устройствам, - например выйти из узла. Первым устройством на выходе из пода будет оверлейное устройство, которое оборачивает проходящий через него трафик в существующую оверлейную сетевую инфраструктуру между подами в кластере. И, наконец, последнее устройство — ens33, которое является основным интерфейсом пода и обеспечивает доступ к внешним компонентам. Хорошо, но как пакеты ходят между разными namespace? В данном случае ключевую роль играет устройство veth, которое необходимо для создания виртуальных подключений между различными сетевыми пространствами имён. Оно обеспечивает связь таким образом? Еще одно ключевое устройство, присутствующее в сетевых подключаемых плагинах уровня 2, — это мостовое устройство br0. Его основная обязанность — позволить подам внутри одного узла общаться друг с другом. Устройство моста заполняет свою собственную таблицу ARP всеми данными пода, чтобы знать, куда должен двигаться каждый пакет. Чтобы не уходить в дебри всего этого сетевого леса, можно подойти к сути и уже сказать про Kubernetes DNS, который занимается направлением трафика и резолвом DNS-имён в кластере. Получается если недоброжелатель получает доступ в под приложения, в котором есть возможность CAP_NET_RAW, то он получает доступ ко всей сети ноды кластера k8s. Так и хочется попробовать! Глава 4. А правда ли всё, что пишут? Попробуем реализовать ARP-spoofing через один из эксплойтов, найденных на просторах github, и проверить теорию, описанную выше. Забегая вперёд скажу, что ARP - это протокол определения адреса, и работает он по следующему принципу. Имеются две машины, находящиеся в одной сети compute-1 и compute-2. С ВМ compute-1 необходимо отправить пакет на compute-2. Для этого ему нужно узнать физический адрес compute-2. Поэтому compute-1 всем компьютерам в одном с ним broadcast domain отправляет запрос следующего содержания “ВМ с виртуальным IP ... сообщите свой MAC-адрес на ВМ c IP 02:00:c0:a8:fb:02 (compute-1)”. После чего он получает необходимые данные для отправки пакетов. Выкачиваем репозиторий и применяем манифесты с подами. Затем смело заходим в каждый из подов, запускаем exploit и смотрим, что у нас получается. Текущий exploit, запущенный из пода, перехватывает и видит весь трафик ноды в k8s. А теперь посмотрим ip-адрес нашего пода hacker и отредактируем в нём файл hosts для exploit следующим образом: google.com. 172.17.0.13 где 172.17.0.13 - ip адрес пода. Теперь вновь повторим действия “злоумышленника”. Запускаем netcat в поде для отправки нашего ответа на 80-ом порту, запускаем exploit и тестируем всё тот же запрос. Что произошло?
apt-get install libcap-ng-utils; pscap -a Ожидаемый вывод будет примерно такой:
Получается, что сейчас вся сеть ноды k8s доступна из одного пода, и если недоброжелатель решит воспользоваться этой возможностью, он может произвести кражу данных пользователей. Как с этим бороться?
Главное, в этом моменте не перестараться и не нарушить работоспособность своего приложения. Глава 5. Доверяй, но проверяй! Но что скажет на это всё другая технология - Kube-bench? Она по своей сути тоже призвана искать уязвимости в инфраструктуре k8s, но немного иным способом, а именно - через анализ конфигураций кластера. Запустим аналогичную проверку посредством этого ПО: apiVersion: batch/v1 kind: Job metadata: name: kube-bench spec: template: metadata: labels: app: kube-bench spec: hostPID: true containers: - name: kube-bench image: docker.io/aquasec/kube-bench:latest command: ["kube-bench"] volumeMounts: - name: var-lib-etcd mountPath: /var/lib/etcd readOnly: true - name: var-lib-kubelet mountPath: /var/lib/kubelet readOnly: true - name: var-lib-kube-scheduler mountPath: /var/lib/kube-scheduler readOnly: true - name: var-lib-kube-controller-manager mountPath: /var/lib/kube-controller-manager readOnly: true - name: etc-systemd mountPath: /etc/systemd readOnly: true - name: lib-systemd mountPath: /lib/systemd/ readOnly: true - name: srv-kubernetes mountPath: /srv/kubernetes/ readOnly: true - name: etc-kubernetes mountPath: /etc/kubernetes readOnly: true - name: usr-bin mountPath: /usr/local/mount-from-host/bin readOnly: true - name: etc-cni-netd mountPath: /etc/cni/net.d/ readOnly: true - name: opt-cni-bin mountPath: /opt/cni/bin/ readOnly: true restartPolicy: Never volumes: - name: var-lib-etcd hostPath: path: "/var/lib/etcd" - name: var-lib-kubelet hostPath: path: "/var/lib/kubelet" - name: var-lib-kube-scheduler hostPath: path: "/var/lib/kube-scheduler" - name: var-lib-kube-controller-manager hostPath: path: "/var/lib/kube-controller-manager" - name: etc-systemd hostPath: path: "/etc/systemd" - name: lib-systemd hostPath: path: "/lib/systemd" - name: srv-kubernetes hostPath: path: "/srv/kubernetes" - name: etc-kubernetes hostPath: path: "/etc/kubernetes" - name: usr-bin hostPath: path: "/usr/bin" - name: etc-cni-netd hostPath: path: "/etc/cni/net.d/" - name: opt-cni-bin hostPath: path: "/opt/cni/bin/" В рамках анализа присутствует 5 разделов:
Мы останавливаемся сразу на последнем, где получаем кучу предупреждений о проблемах в текущих политиках кластера, а также о кратких рекомендациях по их устранению. Здесь мы явно видим те же рекомендации, которые уже описаны выше, и хочется с акцентировать внимание на важном пункте 5.2.7 - рекомендации по отключению NET_RAW. Получается, что какими средствами ни тестируй кластер, а проблема в наличии уязвимости по-прежнему присутствует. Попробуем произвести устранение данной проблемы путём написания PodSecurityPolicy, затем проведём тесты инфраструктуры. Для создания отключения NET_RAW добавили в поде следующие строчки: securityContext: capabilities: drop: ["NET_RAW"] После внесения корректировок в yaml-манифест этой возможности в запущенном контейнере уже не было: Результаты тестирования: Kube-hunter Kube-bench Результат остался не изменен и статус “Warning” никуда не делся. А теперь интрига - данный инструмент в результате вывода проверки предоставляет лишь текстовую рекомендательную часть (Manual) по устранению возможной проблемы в кластере, но не несёт в себе какую-либо проверку в рамках данного раздела. Вывод - результаты с тестированием Kubernetes Policies всегда будут неизменны, и никак не проверяют ваш кластер. Заключение Итак, к чему же было так много слов, и для чего стоит это всё применять? Изначально, когда мы моделировали ситуацию, в которой нам необходимо было улучшить безопасность нашего кластера, не было понятно, какими средствами хотелось бы пользоваться в рамках решения проблемы. Тестируя технологии kube-hunter и kube-bench, можно сказать, что они выполняют свой основной функционал по анализу проблем, но не несут в себе конкретные и правильные рекомендации по их устранению или же выполняют не все необходимые тесты для проверки CIS. Из чего следует, что нельзя доверять всецело их советам и необходимо проводить свой анализ для каждого отдельного случая, чтобы в дальнейшем принять единственно верное решение. Также хочется отметить, что при анализе одной проблемы, мы лишь слегка углубились в бескрайнее болото безопасности инфраструктуры, и что в дальнейшем можно бесконечно долго докапываться до первопричин возникновения угрозы. Для выполнения тех же аудитов безопасности также могут быть использованы krane, statboard, falco и другие технологии, подробное изучение которых можно ещё расписать на отдельную статью или даже книгу. Источник: vk.com Комментарии: |
|