Прим. переводчика: автор статьи предлагает реализацию honeypot'а («приманки») на основе виртуального кластера Kubernetes, чтобы обнаруживать попытки взлома K8s-инфраструктуры. Также в статье рассматриваются отличия низкоинтерактивных и высокоинтерактивных приманок.
Если не вдаваться в детали, главная задача приманок — соблазнять злоумышленников, отвлекая от реальных целей, и попутно собирать информацию об их деятельности. Сегодня мы попытаемся создать такую приманку с помощью vcluster и Falco.
В первой части серии речь пойдет о том, как собрать простую SSH-ловушку для выявления атак, направленных на среду исполнения.
Почему именно приманки
Приманки, или honeypot'ы, могут моделировать практически любой тип цифровых активов, включая приложения, системы, сети, устройства IoT, компоненты SCADA и многое другое. Их сложность варьируется от так называемых honeytoken'ов — отдельных файлов, дополненных соответствующим инструментарием, до honeynets — разветвленных сетей, включающих множество систем и инфраструктурных компонентов.
Приманки подобного типа очень полезны для сбора оперативной информации, поскольку позволяют командам и исследователям, специализирующимся на безопасности, получить представление об инструментах, методах и процедурах злоумышленников, а также выступают основой для индикаторов компрометации* в различных инструментах безопасности.
* Прим. переводчика
Indicators of compromise, IoCs — артефакты, наблюдаемые в сети или в операционной системе, которые с высокой степенью достоверности указывают на вторжение.
Приманки можно классифицировать по уровню сложности: высокоинтерактивные и низкоинтерактивные.
Отличия приманок с разными уровнями сложностями
Низкоинтерактивные приманки — аналог утиного манка в мире инструментов для безопасности. Для их запуска не требуются значительные ресурсы. При этом они, как правило, способны только на базовые действия — например, могут выдавать относительно реалистичный баннер в ответ на запросы на стандартный порт. Обычно этим дело и ограничивается. Такая приманка может заинтересовать злоумышленника при сканировании портов и служб, но отсутствие какой-либо иной активности на принимающей стороне, скорее всего, не увлечет его надолго. Кроме того, низкоинтерактивные приманки не позволяют получить представление о том, что именно делает злоумышленник. Они не обеспечивают достаточной области атаки, с которой тот мог бы взаимодействовать.
Если низкоинтерактивные приманки — это утиные манки, то высокоинтерактивные приманки — это полноценные подсадные утки. Они гораздо лучше заманивают злоумышленников, однако существует риск потерять «утку» в процессе. Высокоинтерактивные приманки часто представляют собой реалистичные системы с реальными работающими приложениями. Они оснащены дополнительными инструментами для тщательного отслеживания вредоносной активности. Это позволяет проследить всю цепочку действий злоумышленников, идентифицировать используемые эксплойты, а также получить копии загружаемых инструментов, двоичных файлов, используемых учетных данных и т. д. С точки зрения сбора полезной информации все это замечательно. Однако не следует забывать, что в руки злоумышленников передается реальный актив, и необходимо тщательно следить за тем, что они с ним делают.
Одна из главных проблем высокоинтерактивных приманок — изоляция атакующего от остального окружения. В случае приманок, построенных с использованием инструментов контейнеризации, таких как Kubernetes, следует внимательно следить за тем, чтобы атакующий не получил доступ к частям кластера, отвечающим за работу приманки. Также нельзя открывать доступ к инструментарию для наблюдения за приманкой и управления ею. Это непростая задача. Частью притягательности приманки приходится жертвовать, защищая ее критические компоненты от доступа злоумышленников. Другими словами, приходится следить за всем, что злоумышленник может использовать для нацеливания на сам кластер или на инструментарий для наблюдения, либо создавать обходные пути для предотвращения нежелательного вмешательства.
Виртуальные кластеры спешат на помощь
Виртуальные кластеры работают поверх основного кластера Kubernetes. Схема позволяет запускать множество виртуальных кластеров. Каждый такой кластер будет находиться в обособленной среде, без какой-либо возможности связаться с другими виртуальными кластерами или с хост-кластером.
Изоляция позволяет раскрывать ключевые внутренние элементы виртуального кластера — ничто не будет указывать, что этот кластер работает поверх другого. Можно раскрывать элементы инфраструктуры Kubernetes, инструменты обслуживания и другие компоненты, не опасаясь за судьбу кластера.
Существуют различные проекты виртуальных кластеров, которые можно использовать для организации приманки. Среди них vcluster выглядит, пожалуй, наиболее перспективно. Кроме того, проект отличается хорошей поддержкой. Ребята из vcluster очень дружелюбны и отзывчивы, обязательно зайдите и поздоровайтесь с ними в Slack'е!
Создаём приманку на vcluster
В этом разделе мы развернем простую приманку с помощью vlcuster. Специально ограничимся базовым примером. Впрочем, он будет хорошим фундаментом, на котором можно строить любые дальнейшие эксперименты.
Нам потребуются следующие инструменты с указанными минимальными версиями:
Minikube v1.26.1;
Helm v3.9.2;
kubectl v1.25.0;
vcluster 0.11.2.
Пошаговая установка приманки на базе vcluster и Falco
Прежде всего необходимо установить исполняемый файл vcluster:
$ curl -s -L "https://github.com/loft-sh/vcluster/releases/latest" | sed -nE 's!.*"([^"]*vcluster-linux-amd64)".*!https://github.com\1!p' | xargs -n 1 curl -L -o vcluster && chmod +x vcluster;
1 curl -L -o vcluster && chmod +x vcluster;
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 36.8M 100 36.8M 0 0 10.4M 0 0:00:03 0:00:03 --:--:-- 11.2M
$ sudo mv vcluster /usr/local/bin;
$ vcluster version
vcluster version 0.11.2
Разворачиваем локальный кластер Kubernetes
Создать кластер можно множеством способов. В нашем случае мы воспользуемся Minikube.
Примечание:
Нам подходят драйверы
virtualbox
,qemu
илиkvm2
для Minikube, но не драйверnone
. Falco не сможет правильно развернуть свой драйвер, если использоватьnone
.Кроме того, поскольку используется драйвер
virtualbox
, развертывание необходимо проводить на реальном оборудовании. Драйвер не будет работать в виртуальной машине, в инстансе EC2 и аналогичных средах.
Давайте создадим кластер. После запуска команды start minikube
несколько минут будут собираться все нужные компоненты:
$ minikube start --vm-driver=virtualbox
???? minikube v1.26.1 on Ubuntu 22.04
✨ Using the virtualbox driver based on user configuration
???? Starting control plane node minikube in cluster minikube
???? Creating virtualbox VM (CPUs=2, Memory=6000MB, Disk=20000MB) ...
???? Preparing Kubernetes v1.24.3 on Docker 20.10.17 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
???? Verifying Kubernetes components...
???? Enabled addons: storage-provisioner
???? Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
Добавляем в приманку инструментарий Falco
Теперь нужно установить Falco:
$ helm repo add falcosecurity https://falcosecurity.github.io/charts
"falcosecurity" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "falcosecurity" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm upgrade --install falco --set driver.loader.initContainer.image.tag=master --set driver.loader.initContainer.env.DRIVER_VERSION="2.0.0+driver" --set tty=true --namespace falco --create-namespace falcosecurity/falco
Release "falco" does not exist. Installing it now.
NAME: falco
LAST DEPLOYED: Thu Sep 8 15:32:45 2022
NAMESPACE: falco
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Falco agents are spinning up on each node in your cluster. After a few
seconds, they are going to start monitoring your containers looking for
security issues.
No further action should be required.
Tip:
You can easily forward Falco events to Slack, Kafka, AWS Lambda and more with falcosidekick.
Full list of outputs: https://github.com/falcosecurity/charts/tree/master/falcosidekick.
You can enable its deployment with `--set falcosidekick.enabled=true` or in your values.yaml.
See: https://github.com/falcosecurity/charts/blob/master/falcosidekick/values.yaml for configuration values.
На запуск Pod'а с Falco уйдет несколько минут. Проверить его состояние и просмотреть журналы, чтобы убедиться, что все идет гладко, можно с помощью kubectl
:
$ kubectl get pods -n falco -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
falco-zwfcj 1/1 Running 0 73s 172.17.0.3 minikube <none> <none>
$ kubectl logs falco-zwfcj -n falco
Defaulted container "falco" out of: falco, falco-driver-loader (init)
Thu Sep 8 22:32:47 2022: Falco version 0.32.2
Thu Sep 8 22:32:47 2022: Falco initialized with configuration file /etc/falco/falco.yaml
Thu Sep 8 22:32:47 2022: Loading rules from file /etc/falco/falco_rules.yaml:
Thu Sep 8 22:32:47 2022: Loading rules from file /etc/falco/falco_rules.local.yaml:
Thu Sep 8 22:32:48 2022: Starting internal webserver, listening on port 8765
Собираем всё вместе и создаем виртуальный кластер
Теперь необходимо создать пространство имен для виртуального кластера в основном и развернуть в нем виртуальный:
$ kubectl create namespace vcluster
namespace/vcluster created
$ vcluster create ssh -n vcluster
info Detected local kubernetes cluster minikube. Will deploy vcluster with a NodePort & sync real nodes
info Create vcluster ssh...
info execute command: helm upgrade ssh https://charts.loft.sh/charts/vcluster-0.11.2.tgz --kubeconfig /tmp/3673995455 --namespace vcluster --install --repository-config='' --values /tmp/641812157
done √ Successfully created virtual cluster ssh in namespace vcluster
info Waiting for vcluster to come up...
warn vcluster is waiting, because vcluster pod ssh-0 has status: ContainerCreating
done √ Switched active kube context to vcluster_ssh_vcluster_minikube
- Use `vcluster disconnect` to return to your previous kube context
- Use `kubectl get namespaces` to access the vcluster
Устанавливаем SSH-приманку
Виртуальный кластер готов. Теперь в нем можно создать незащищенный SSH-сервер и использовать его в качестве мишени.
Для этого воспользуемся специальным небезопасным Helm-чартом SSH-сервера от sourcecodebox.io. Учетные данные для этого сервера — root/THEPASSWORDYOUCREATED
.
$ helm repo add securecodebox https://charts.securecodebox.io/
"securecodebox" has been added to your repositories
$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "falcosecurity" chart repository
...Successfully got an update from the "securecodebox" chart repository
Update Complete. ⎈Happy Helming!⎈
$ helm install my-dummy-ssh securecodebox/dummy-ssh --version 3.14.3
NAME: my-dummy-ssh
LAST DEPLOYED: Thu Sep 8 15:53:15 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Demo SSH Server deployed.
Note this should used for demo and test purposes.
Do not expose this to the Internet!
Изучаем разные контексты
Итак, внутри виртуального кластера теперь у нас работает некий сервис. Давайте рассмотрим два различных контекста.
Примечание:
Контекст в Kubernetes — это набор параметров для доступа к определенному кластеру. Переключение контекста меняет всё окружение для команд вроде
kubectl
с одного кластера на другой.
Сперва давайте взглянем на все ресурсы, существующие в кластере, с точки зрения виртуального кластера:
$ kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system pod/coredns-6ffcc6b58-h7zwx 1/1 Running 0 m26s
default pod/my-dummy-ssh-f98c68f95-vwns 1/1 Running 0 m1s
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.112.178 <none> 443/TCP m26s
kube-system service/kube-dns ClusterIP 10.97.196.120 <none> 53/UDP,53/TCP,9153/TCP m26s
default service/my-dummy-ssh ClusterIP 10.99.109.0 <none> 22/TCP m1s
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 m26s
default deployment.apps/my-dummy-ssh 1/1 1 1 m1s
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-6ffcc6b58 1 1 1 m26s
default replicaset.apps/my-dummy-ssh-f98c68f95 1 1 1 m1s
Видна обычная инфраструктура Kubernetes, а также Pod и сервис my-dummy-ssh
, запущенные в пространстве имен default
. Обратите внимание, что ресурсы Falco не отображаются, поскольку последний установлен в хост-кластере и не виден из виртуального кластера.
Теперь давайте переключим контексты, отключившись от виртуального кластера. Это вернет нас к контексту хост-кластера:
$ vcluster disconnect
info Successfully disconnected from vcluster: ssh and switched back to the original context: minikube
Если теперь попросить kubectl
еще раз вывести список ресурсов, картина будет совсем иной:
$ kubectl get all --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
falco pod/falco-zwfcj 1/1 Running 0 5m
kube-system pod/coredns-d4b75cb6d-ttwdl 1/1 Running 0 4m
kube-system pod/etcd-minikube 1/1 Running 0 4m
kube-system pod/kube-apiserver-minikube 1/1 Running 0 4m
kube-system pod/kube-controller-manager-minikube 1/1 Running 0 4m
kube-system pod/kube-proxy-dhg9v 1/1 Running 0 4m
kube-system pod/kube-scheduler-minikube 1/1 Running 0 4m
kube-system pod/storage-provisioner 1/1 Running 0 4m
vcluster pod/coredns-6ffcc6b58-h7zwx-x-kube-system-x-ssh 1/1 Running 0 1m
vcluster pod/my-dummy-ssh-f98c68f95-vwns-x-default-x-ssh 1/1 Running 0 5m
vcluster pod/ssh-0 2/2 Running 0 1m
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4m
kube-system service/kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 4m
vcluster service/kube-dns-x-kube-system-x-ssh ClusterIP 10.97.196.120 <none> 53/UDP,53/TCP,9153/TCP 1m
vcluster service/my-dummy-ssh-x-default-x-ssh ClusterIP 10.99.109.0 <none> 22/TCP 5m
vcluster service/ssh NodePort 10.96.112.178 <none> 443:31530/TCP 1m
vcluster service/ssh-headless ClusterIP None <none> 443/TCP 1m
vcluster service/ssh-node-minikube ClusterIP 10.102.36.118 <none> 10250/TCP 1m
NAMESPACE NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
falco daemonset.apps/falco 1 1 1 1 1 <none> 5m
kube-system daemonset.apps/kube-proxy 1 1 1 1 1 kubernetes.io/os=linux 4m
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
kube-system deployment.apps/coredns 1/1 1 1 4m
NAMESPACE NAME DESIRED CURRENT READY AGE
kube-system replicaset.apps/coredns-d4b75cb6d 1 1 1 4m
NAMESPACE NAME READY AGE
vcluster statefulset.apps/ssh 1/1 1m
Видны ресурсы Falco и ресурсы SSH-инсталляции из виртуального кластера. На этот раз они отображаются как работающие в пространстве имен vcluster
на хост-кластере.
Испытываем приманку
Наконец у нас все готово! Давайте сделаем какую-нибудь гадость, чтобы сработало правило Falco, и посмотрим, что из этого получится.
Сымитировать реальное вторжение нам помогут три терминальных окна.
Терминал 1
В первом окне мы настроим проброс портов, открыв SSH-сервер для локальной машины. Окно должно оставаться открытым, чтобы SSH-сессия оставалась активной.
kubectl port-forward svc/my-dummy-ssh 5555:22
Эта команда откроет сервис на 127.0.0.1
, порт 5555
. Теперь нужно убедиться, что для этого окна используется контекст vcluster
. Если используется контекст для основного кластера, переключиться на нужный можно с помощью команды vcluster connect ssh -n vcluster
:
$ kubectl port-forward svc/my-dummy-ssh 5555:22
Forwarding from 127.0.0.1:5555 -> 22
Forwarding from [::1]:5555 -> 22
Терминал 2
В этом окне мы подключимся по SSH к сервису, который только что открыли на порту 5555
. Учетные данные: root/THEPASSWORDYOUCREATED
:
$ ssh -p 5555 root@127.0.0.1
The authenticity of host '[127.0.0.1]:5555 ([127.0.0.1]:5555)' can't be established.
ED25519 key fingerprint is SHA256:eLwgzyjvrpwDbDr+pDbIfUhlNANB4DPH9/0w1vGa87E.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[127.0.0.1]:5555' (ED25519) to the list of known hosts.
root@127.0.0.1's password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 5.10.57 x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
Подключившись по SSH, мы теперь мечтаем сделать какую-нибудь гадость, чтобы сработало правило Falco. Например, можно посмотреть /etc/shadow
:
root@my-dummy-ssh-7f98c68f95-5vwns:~# cat /etc/shadow
root:$6$hJ/W8Ww6$pLqyBWSsxaZcksn12xZqA1Iqjz.15XryeIEZIEsa0lbiOR9/3G.qtXl/SvfFFCTPkElo7VUD7TihuOyVxEt5j/:18281:0:99999:7:::
daemon:*:18275:0:99999:7:::
bin:*:18275:0:99999:7:::
sys:*:18275:0:99999:7:::
sync:*:18275:0:99999:7:::
<snip>
Терминал 3
В этом окне будем просматривать логи от Pod'а Falco:
$ kubectl logs falco-zwfcj -n falco
23:22:26.726981623: Notice Redirect stdout/stdin to network connection (user=root user_loginuid=-1 k8s.ns=vcluster k8s.pod=my-dummy-ssh-7f98c68f95-5vwns-x-default-x-ssh container=cffc68f50e06 process=sshd parent=sshd cmdline=sshd -D terminal=0 container_id=cffc68f50e06 image=securecodebox/dummy-ssh fd.name=172.17.0.1:40312->172.17.0.6:22 fd.num=1 fd.type=ipv4 fd.sip=172.17.0.6)
23:22:27.709831799: Warning Sensitive file opened for reading by non-trusted program (user=root user_loginuid=0 program=cat command=cat /etc/shadow file=/etc/shadow parent=bash gparent=sshd ggparent=sshd gggparent=<NA> container_id=cffc68f50e06 image=securecodebox/dummy-ssh) k8s.ns=vcluster k8s.pod=my-dummy-ssh-7f98c68f95-5vwns-x-default-x-ssh container=cffc68f50e06
Видно множество строк вида Notice Redirect stdout/stdin to network connection
— результат проброса портов. Кроме того, есть сообщения с Warning Sensitive file opened for read by non-trusted program
— результат нашей попытки прочитать /etc/shadow
.
Вот оно! Это Falco сигнализирует о том, что кто-то копается в вещах, не предназначенных для его глаз, подключившись к нашей приманке через SSH. И все это происходит внутри виртуального кластера vcluster, который, в свою очередь, работает в хост-кластере.
Убираем за собой
Убрать за собой беспорядок или начать все сначала (если дела пойдут настолько плохо) можно в несколько команд: удалите Falco и сервер SSH, разберитесь с Minikube и очистите временные файлы:
$ helm delete falco --namespace falco; helm delete my-dummy-ssh --namespace default; minikube delete --all -purge; sudo rm /tmp/juju*
release "falco" uninstalled
release "my-dummy-ssh" uninstalled
???? Deleting "minikube" in virtualbox ...
???? Removed all traces of the "minikube" cluster.
???? Successfully deleted all profiles
[sudo] password for user:
Стойте, это еще не все!
Виртуальные кластеры чрезвычайно перспективны для исследований в области безопасности в целом и для организации приманок в частности. Область, несомненно, интересная для наблюдения, как для будущих разработок, так и с точки зрения применения этих инструментов технологической отраслью.
В этой статье мы заложили хорошее начало, хотя многое еще можно отшлифовать и улучшить.
Следите за нашими публикациями — в следующей части этой серии мы добавим механизм реагирования на базе Falco Sidekick, запустим новые приманки во втором виртуальном кластере и подкрутим их настройки, сделав более безопасными.
P.S.
Читайте также в нашем блоге:
ZeroBot-Dot
Спасибо. Нашли мне занятие на выходные )