Блог
Защита от побега из контейнера: Практическое руководство по изоляции Docker для многопользовательского хостинга
Узнайте, как защитить контейнеры Docker от уязвимостей побега и сбоев изоляции в многопользовательских средах с помощью конкретных шагов и примеров.

Краткое содержание
Контейнеры Docker используют общий хост-ядро, что делает изоляцию критически важной — особенно в многопользовательском хостинге, где один побег из контейнера может скомпрометировать всех арендаторов. Многие разработчики полагают, что контейнеры — это идеально изолированные виртуальные машины, но реальность иная. В этой статье объясняются функции ядра Linux, лежащие в основе изоляции Docker (пространства имен, cgroups), и векторы атак, которые им угрожают. Вы узнаете практические шаги по усилению вашей настройки Docker: ограничение привилегий, использование безопасной среды выполнения, сканирование образов и сегментация сети. Следуя примеру поставщика многопользовательского хостинга WordPress из реального мира, вы увидите, как применять эти меры защиты. Мы также рассмотрим оговорки, такие как компромиссы в производительности и использование seccomp/AppArmor. Цель — предоставить вам надежную стратегию изоляции, которая предотвращает побеги из контейнеров и обеспечивает безопасность ваших арендаторов.
Введение
Если вы управляете многопользовательской хостинговой платформой — будь то общий хостинг WordPress, SaaS-приложение или служба сред разработки — побег из контейнера является сценарием кошмара. Уязвимость в ядре или неправильная конфигурация могут позволить одному арендатору вырваться из своего контейнера и получить доступ к данным других арендаторов или к самому хосту. Изоляция Docker полагается на функции ядра Linux, такие как пространства имен и cgroups, но стандартные конфигурации часто недостаточны для надежной безопасности. Эта статья проведет вас через векторы атак и предоставит действенные шаги для защиты ваших контейнеров Docker, проиллюстрированные примером многопользовательского хостинга WordPress из реального мира. Для более широкого обзора оркестрации в производственной среде см. наше руководство по Оркестрация готовых к производству контейнерных приложений.
Понимание изоляции Docker
Контейнеры Docker используют пространства имен Linux для обеспечения изоляции на уровне процессов: пространства имен PID изолируют деревья процессов, сетевые пространства имен разделяют сетевые интерфейсы, пространства имен монтирования изолируют точки монтирования файловой системы, а пространства имен пользователей позволяют сопоставлять корень контейнера с непривилегированным пользователем хоста. Группы управления (cgroups) ограничивают использование ресурсов, таких как ЦП, память и ввод-вывод диска. Эти функции вместе создают «песочницу» вокруг каждого контейнера. Однако, в отличие от виртуальной машины, которая запускает отдельное ядро, контейнеры используют общее хост-ядро. Это означает, что уязвимость в ядре (например, CVE-2022-0492) может быть использована для побега из изоляции пространства имен контейнера. Кроме того, неправильные конфигурации, такие как запуск контейнеров от имени root внутри контейнера, предоставление контейнеру всех возможностей или не отбрасывание ненужных возможностей Linux, могут расширить поверхность атаки.
Векторы атак
Общие векторы атак включают:
- Эксплойты ядра: Использование ошибки в хост-ядре для получения доступа к хосту.
- Привилегированные контейнеры: Запуск с
--privilegedпредоставляет все возможности и обходит большинство мер изоляции. - Злоупотребление возможностями: Даже без полного привилегированного режима контейнер с опасными возможностями, такими как
CAP_SYS_ADMINилиCAP_NET_ADMIN, может монтировать файловые системы или манипулировать сетевыми настройками. - Небезопасные практики работы с образами: Использование базовых образов с известными уязвимостями или включение ненужных инструментов, таких как компиляторы или интерпретаторы командной строки.
- Общие пространства имен монтирования: Монтирование каталогов хоста в контейнеры может привести к побегу, если они не доступны только для чтения.
Практические шаги по обеспечению безопасности
1. Запуск контейнеров от имени непривилегированного пользователя
По умолчанию Docker запускает контейнеры от имени root внутри контейнера. Если злоумышленник получит root-доступ внутри контейнера, у него будет больше рычагов. Создайте пользователя в вашем Dockerfile и используйте директиву USER. Также избегайте использования флага --user в Docker Compose для сопоставления с произвольным пользователем хоста, если это возможно.
2. Отбросить все возможности и добавить только необходимые
Возможности Linux разбивают привилегии суперпользователя на более мелкие единицы. В Docker Compose используйте cap_drop: ALL, а затем cap_add только необходимые (например, NET_BIND_SERVICE). Избегайте опасных возможностей, таких как SYS_ADMIN, NET_ADMIN, SYS_PTRACE.
3. Использовать корневую файловую систему только для чтения
Установите read_only: true в определении вашего контейнера. Это предотвратит запись злоумышленниками в файловую систему контейнера. Если вашему приложению необходимо записывать временные файлы, смонтируйте том tmpfs в этом месте.
4. Включить переназначение пространств имен пользователей
Переназначение пространств имен пользователей сопоставляет пользователя root контейнера с непривилегированным пользователем хоста. Это добавляет уровень изоляции, поскольку даже если root контейнера совершит побег, он будет иметь привилегии переназначенного пользователя. Включите его в /etc/docker/daemon.json с помощью "userns-remap": "default". Имейте в виду, что это может усложнить права доступа к томам. Для получения более подробной информации см. Мастерство изоляции Docker для безопасного и эффективного веб-хостинга.
5. Применять профили Seccomp и AppArmor/AppArmor
Seccomp ограничивает системные вызовы, которые может выполнять контейнер. Docker предоставляет профиль seccomp по умолчанию, который блокирует опасные системные вызовы. Вы также можете создавать пользовательские профили. Аналогично, AppArmor (или SELinux) обеспечивает обязательный контроль доступа. Используйте AppArmor для ограничения вашего контейнера минимальным набором разрешенных операций. Профиль безопасности можно установить через security_opt в Docker Compose.
6. Использовать минимальные базовые образы и сканировать на наличие уязвимостей
Выбирайте небольшие образы, такие как Alpine или Distroless, которые имеют меньшую поверхность атаки. Регулярно сканируйте образы с помощью таких инструментов, как Docker Scout, Trivy или Clair. Интегрируйте сканирование в ваш конвейер CI/CD, чтобы предотвратить развертывание уязвимых образов.
7. Сегментация сети с помощью пользовательских мостовых сетей
Создавайте отдельные мостовые сети для каждого арендатора или уровня приложений. Это ограничивает трафик между ними (east-west). В Docker Compose определяйте сети и изолируйте службы. Используйте internal: true, если службе не нужен доступ в Интернет. Правила брандмауэра на хосте дополнительно ограничивают трафик между контейнерами.
8. Ограничение ресурсов с помощью Cgroups
Установите лимиты ЦП и памяти в Docker Compose, используя deploy.resources.limits. Это предотвращает запуск атаки исчерпания ресурсов скомпрометированным контейнером. Кроме того, установите kernel_memory и memory_reservation для более точного контроля.
Пример из реального мира: Многопользовательский хостинг WordPress с Docker Compose
Рассмотрим сценарий, когда вы размещаете несколько сайтов WordPress для разных клиентов, каждый в своем контейнере Docker. Небезопасная настройка может выглядеть так:
version: '3'
services:
wordpress:
image: wordpress:latest
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- ./wp-content:/var/www/html/wp-content
db:
image: mysql:5.7
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_ROOT_PASSWORD: somewordpress
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Эта настройка уязвима: контейнер WordPress запускается от имени root внутри, имеет все возможности (поскольку ни одна не отброшена), монтирует каталог хоста с доступом на запись и имеет неограниченный сетевой доступ.
Теперь давайте усилим ее:
version: '3'
services:
wordpress:
image: wordpress:latest
user: www-data
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /var/www/html/wp-content/plugins
security_opt:
- seccomp=seccomp-profile.json
- apparmor=wordpress-profile
networks:
- frontend
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: exampleuser
WORDPRESS_DB_PASSWORD: examplepass
WORDPRESS_DB_NAME: exampledb
volumes:
- wp-uploads:/var/www/html/wp-content/uploads
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
db:
image: mysql:5.7
user: mysql
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
networks:
- backend
environment:
MYSQL_DATABASE: exampledb
MYSQL_USER: exampleuser
MYSQL_PASSWORD: examplepass
MYSQL_ROOT_PASSWORD: somewordpress
volumes:
- db_data:/var/lib/mysql
deploy:
resources:
limits:
cpus: '0.25'
memory: 128M
networks:
frontend:
driver: bridge
internal: false
backend:
driver: bridge
internal: true
volumes:
wp-uploads:
db_data:
Ключевые улучшения:
- Оба контейнера работают от имени непривилегированных пользователей (
www-dataиmysql). - Все возможности отброшены, добавлена только
NET_BIND_SERVICE. - Файловая система WordPress доступна только для чтения, за исключением монтирования tmpfs и тома uploads.
- Применяются профили Seccomp и AppArmor (вам потребуется предоставить пользовательские профили).
- Раздельные сети изолируют веб от базы данных, при этом сеть базы данных является внутренней.
- Лимиты ресурсов предотвращают исчерпание ресурсов.
Дополнительную информацию об усилении безопасности Docker для WordPress см. в статье Docker для WordPress: почему изолированные контейнеры меняют все.
Оговорки
- Переназначение пространств имен пользователей: Хотя это и мощно, это нарушает монтирование томов, поскольку переназначенный UID хоста не совпадает с UID контейнера. Вам может потребоваться предварительно создать каталоги с правильными правами доступа или использовать тома Docker с поддержкой переназначения.
- Профили Seccomp/AppArmor: Пользовательские профили требуют понимания шаблонов системных вызовов и доступа к файлам вашего приложения. Чрезмерно ограничительные профили могут нарушить функциональность. Тщательно тестируйте.
- Производительность: Дополнительные уровни безопасности, такие как seccomp и AppArmor, имеют минимальные накладные расходы, но лимиты ресурсов и файловые системы только для чтения могут повлиять на приложения с интенсивной записью.
- Сложность оркестрации: В многопользовательской среде управление файлами Docker Compose для каждого арендатора может стать громоздким. Рассмотрите возможность использования инструмента оркестрации более высокого уровня, такого как Kubernetes, но это вносит свои собственные соображения безопасности.
Заключение
Побег из контейнера — это реальная угроза в многопользовательском хостинге Docker, но ее можно предотвратить. Понимая механизмы изоляции и применяя многоуровневую защиту — отбрасывая возможности, запуская от имени непривилегированного пользователя, включая пространства имен пользователей, seccomp, AppArmor, сегментацию сети и регулярное сканирование образов — вы можете значительно снизить риск. Помните, что настройки Docker по умолчанию не готовы к производству для многопользовательских рабочих нагрузок. Внедрите эти шаги сегодня, чтобы защитить своих арендаторов и свою инфраструктуру. Для полного обзора лучших практик безопасности Docker обратитесь к Защита ваших веб-приложений с помощью Docker: практическое руководство по изоляции и лучшим практикам.
Sources (5)
- Docker and Container Isolation - Medium
- What is container isolation? Mechanisms, limitations, and secure runtimes | Blog - Northflank
- Container Isolation Explained for Kubernetes and Beyond - Edera
- Docker Security: 5 Risks and 12 Best Practices for Securing Your Containers - Tigera.io
- 9 Security Best Practices for Docker Containers - Kinsta®

