Руководство по безопасности для белорусских компаний
Контейнеризация стала кровеносной системой современной IT-инфраструктуры. Мы упаковываем микросервисы в Docker, оркестрируем их через Kubernetes и наслаждаемся скоростью доставки кода (Time-to-Market). Но в этой гонке за гибкостью мы часто забываем, что контейнер — это не виртуальная машина. Это всего лишь процесс в Linux с набором ограничений (namespaces и cgroups), которые далеко не всегда так надежны, как кажется.
Как специалист, регулярно проводящий аудиты безопасности (Penetration Testing), я вижу одну и ту же картину: идеально написанный код бизнес-логики работает в «дырявом» окружении.
В этой статье мы разберем векторы атак на инфраструктуру, способы выхода на хост и требования Оперативно-аналитического центра (ОАЦ), выполнение которых необходимо для аттестации систем в Беларуси.
Уровень 1: «Открытая форточка». Проникновение через приложение
Любая атака на кластер начинается с малого. Злоумышленнику не обязательно искать 0-day уязвимость в ядре, если веб-приложение любезно предоставляет командную оболочку.
Иллюзия изоляции
Многие разработчики ошибочно полагают, что если приложение взломают, хакер останется «запертым» внутри контейнера. Это фатальное заблуждение. Внутри контейнера злоумышленник получает плацдарм для разведки сети, доступ к переменным окружения и, что самое критичное, доступ к токенам сервисных аккаунтов.
Пример уязвимой реализации
Представьте микросервис, где разработчик допустил прямую конкатенацию строк в запросе к базе данных.
# app.py - пример уязвимого кода (псевдокод)
@app.route('/user/<user_id>')
def get_user(user_id):
# ОШИБКА: Отсутствие параметризации
# Атакующий подставляет условия в строку запроса
query = "SELECT [данные] FROM users WHERE id = " + user_id
cursor.execute(query)
return cursor.fetchall()Если приложение допускает удаленное выполнение команд (RCE), например, через некорректную обработку файлов, мы получаем shell.
# Критическая ошибка: вызов системной утилиты с параметрами пользователя
# Атакующий может передать: "http://site.com ; cat /token"
os.system("utility_name " + user_input_url)Инъекция команды позволяет прочитать файл с токеном: /var/run/secrets/kubernetes.io/serviceaccount/token. С этим токеном хакер становится авторизованным пользователем Kubernetes API.
Взгляд аудитора (Compliance ОАЦ)
Согласно требованиям регулятора (в т.ч. Приказ ОАЦ №130), подобные инциденты должны фиксироваться.
- Сбор событий: Если злоумышленник отправляет подозрительные запросы, ваш WAF или приложение обязаны отправить лог в SIEM.
- Единое время: Важнейший нюанс — синхронизация времени. Если в контейнере UTC, а в логах хоста UTC+3, корреляция событий невозможна. ОАЦ рекомендует использование источников времени БелГИМ.
Уровень 2: Container Escape. Побег из Шоушенка
Если первый этап — это взлом входной двери, то Container Escape — это разрушение стен. Цель — выйти из изолированного пространства контейнера и получить контроль над операционной системой хоста (Node).
Техника 1: Docker Socket (Самая распространенная ошибка)
Часто для CI/CD процессов внутрь контейнера монтируют сокет докера: /var/run/docker.sock. Это равносильно выдаче прав администратора на хосте.
Имея доступ к сокету, злоумышленник внутри контейнера может отправить запрос Docker Daemon (который работает на хосте) на создание нового контейнера.
Сценарий атаки:
- Хакер формирует HTTP-запрос к сокету.
- В параметрах указывает: «Запусти образ Ubuntu, примонтируй корень хоста / в папку /host и дай права Privileged».
- После запуска он получает полный доступ к файловой системе сервера через папку /host.
Техника 2: Эксплуатация cgroup v1 (CVE-2022-0492)
Это более тонкая атака, демонстрирующая важность обновления ядра. Уязвимость позволяет контейнеру, запущенному с высокими привилегиями, выйти за пределы изоляции через особенности механизма контрольных групп (cgroup).
Ядро Linux обращается к специальному файлу-агенту, когда процесс в группе завершается. Если контейнер имеет возможность записи в конфигурацию cgroup (что часто возможно без жестких политик), он может зарегистрировать вместо стандартного агента свой исполняемый код.
Условия для вектора атаки:
- Контейнер работает от имени суперпользователя (root).
- Не активированы модули защиты типа AppArmor или SELinux.
- Отсутствует профиль seccomp.
Этот пример наглядно показывает, почему требование запускать сервисы от непривилегированных пользователей (директива USER 1001) — это необходимость.
Уровень 3: Захват Kubernetes (K8s) через RBAC
Кластер Kubernetes — это сложная система. Получив доступ к API Server, злоумышленник становится «богом» инфраструктуры.
Атака через Service Account
Если администратор выдал Service Account (SA) излишние права (например, cluster-admin), последствия будут катастрофическими.
Сценарий:
- Хакер получает доступ в контейнер и крадет токен SA.
- Использует kubectl или API для создания привилегированного Пода.
Пример опасной конфигурации, которую создает хакер:
# Фрагмент манифеста атаки
spec:
containers:
- image: alpine
# Команда для входа в пространство имен хоста
command: ["nsenter", "--mount=...", "--", "bash"]
securityContext:
privileged: true
# Доступ к сети и процессам хоста
hostNetwork: true
hostPID: trueИспользуя nsenter и hostPID, атакующий получает доступ к процессам Master-ноды и базе данных etcd, где хранятся все секреты кластера.
Чек-лист безопасности и требования регулятора
При проведении аттестации системы защиты информации (СЗИ) для контейнерных сред в Беларуси, аудиторы проверяют следующие аспекты:
1. Управление уязвимостями
Вы не можете выпустить в прод образ, который не прошел сканирование.
- Инструменты: Trivy, Grype, Clair.
- Процесс: CI/CD пайплайн должен останавливаться, если найдены уязвимости уровня High или Critical.
- Документация: Если патча нет, должен быть документ «Risk Acceptance» с компенсирующими мерами.
2. Защита данных и секретов
- Encryption at Rest: База etcd должна быть зашифрована. В «ванильном» Kubernetes это часто выключено по умолчанию.
- Секреты: Запрет на хранение паролей в переменных окружения в открытом виде. Используйте Vault или шифрование Secret-ресурсов.
3. Сетевая сегментация
По умолчанию в Kubernetes «Flat Network» — все поды видят друг друга. Это недопустимо.
- Используйте CNI с поддержкой политик (Cilium, Calico).
- Принцип Default Deny: запретите весь трафик, а затем разрешайте только необходимое.
4. Supply Chain Security
Откуда вы берете образы?
- Использование публичных Docker Hub образов без проверки недопустимо.
- Необходим локальный доверенный реестр (Harbor, Artifactory).
- Подпись образов: Вы должны быть уверены, что запущенный образ — это именно тот код, который собрал CI-сервер.
Практические рекомендации
Чтобы спать спокойно и пройти проверки, внедрите эшелонированную оборону.
Runtime Security
Внедрите Falco для мониторинга аномалий в реальном времени. Напишите правило, запрещающее запуск shell в контейнерах на проде.
Policy as Code (OPA / Kyverno)
Человеческий фактор — главная уязвимость. Запретите создание небезопасных подов на уровне API. Используйте Kyverno для принудительного контроля:
- Запрет privileged: true.
- Запрет монтирования сокетов.
- Требование runAsNonRoot: true.
Итог
Безопасность контейнеров — это не состояние, а процесс. Соответствие требованиям ОАЦ в этой области — это не просто бюрократия. Требования регулятора написаны опытом скомпрометированных систем. Реализуя их, вы строите реальный бастион вокруг ваших данных.