Принцип наименьших привилегий в Docker: руководство по Linux Capabilities

Принцип наименьших привилегий в Docker: руководство по Linux Capabilities

Запуск контейнеров от root — это лишний риск. Рассказываем, как предоставлять процессам только те привилегии, которые им действительно нужны, и усилить безопасность Docker-окружения.

В мире, где виртуализация и контейнеризация стали основой инфраструктуры, вопрос изоляции и ограничения прав процессов выходит на первый план. Независимо от того, работает ли ваш проект на локальном сервере, в облаке или на VPS, минимизация привилегий позволяет снизить поверхность атак и обеспечить более предсказуемое и управляемое поведение приложений.

Введение

Лого Docker

Традиционный подход к безопасности в Docker часто сводится к бинарному выбору: либо контейнер работает с полными правами root, либо с ограниченными возможностями непривилегированного пользователя через опцию --user. Однако ни один из этих вариантов не является идеальным решением. Запуск от root создает риски полной компрометации системы, в то время как обычный пользователь часто не имеет необходимых привилегий для работы приложения.

Linux capabilities («возможности») — это механизм управления привилегиями, когда монолитные права суперпользователя дробятся на отдельные составляющие. Вместо того чтобы предоставлять процессу все возможности root-пользователя, система позволяет выборочно назначать только те права, которые действительно необходимы для работы приложения. Например, веб-серверу может потребоваться только возможность привязки к привилегированным портам (CAP_NET_BIND_SERVICE), без доступа к другим системным функциям.

Такое избирательное назначение привилегий значительно уменьшает поверхность атаки и потенциальный ущерб от возможного взлома. Даже если злоумышленнику удастся скомпрометировать процесс внутри контейнера, его возможности будут ограничены только теми правами, которые были явно предоставлены через capabilities. Это реализация принципа наименьших привилегий на уровне отдельных системных функций, а не всего процесса в целом.

Аренда VPS/VDS — от ₽219/месяц

Почему выбирают VPS от AdminVPS:

✓ Дешевле физического сервера

✓ Более гибкий и мощный, чем обычный хостинг

✓ Бесплатная защита от DDoS и техподдержка 24/7

✓ Масштабируется под любые задачи

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

popup12

Опасные возможности и их риски

CAP_SYS_ADMIN — одна из наиболее опасных возможностей, поскольку объединяет в себе множество привилегий, традиционно ассоциируемых с root-доступом. Она позволяет монтировать и размонтировать файловые системы, настраивать параметры сети, управлять пространствами имён и изменять системные часы. В контексте контейнеризации это создаёт риск несанкционированного доступа к хостовым ресурсам и обхода изоляции.

CAP_NET_RAW предоставляет возможность создавать raw-сокеты, что необходимо для работы таких утилит как ping и traceroute. Однако эта же возможность позволяет осуществлять сетевое сканирование, создавать кастомные сетевые пакеты и проводить ARP-спуфинг. Злоумышленник может использовать её для анализа внутренней сети и проведения атак типа «man-in-the-middle».

CAP_SYS_MODULE даёт право загружать и выгружать модули ядра Linux. Это создаёт прямую угрозу целостности ядра операционной системы — возможность загрузки вредоносных или нестабильных модулей, обхода security-политик и модификации системных вызовов.

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

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

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

Методы защиты:

  • регулярный аудит используемых capabilities в запущенном контейнере с помощью команд:
docker exec <container_name> capsh --print

или для краткого просмотра:

docker exec <container_name> getpcaps 1
  • использование минимального набора привилегий,
  • мониторинг попыток использования опасных возможностей через auditd,
  • запрет на использование опасных возможностей в продакшене.

Ограничение привилегий

Стандартной практикой безопасности при работе с Docker-контейнерами является выдача минимальных привилегий. Реализуется это через комбинацию флагов --cap-drop (отзыв привилегий) и --cap-add (выдача). Базовый шаблон выглядит следующим образом:

docker run --cap-drop=ALL --cap-add=<capability> <image>

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

Для просмотра текущих возможностей, активных в запущенном контейнере, используются две основные команды. Просмотр полной информации о возможностях через capsh (требует наличия libcap2-bin в системе):

docker exec <container> capsh --print

Краткий вывод для конкретного процесса:

docker exec <container> getpcaps 1

Команда capsh --print предоставляет детальную информацию о наборе возможностей, включая:

  • текущие эффективные (effective) возможности,
  • наследуемые (inheritable) возможности,
  • периметры безопасности (bounding set),
  • поддержку возможностей ядром.

Команда getpcaps 1 показывает возможности процесса с PID 1 (обычно основного процесса в контейнере) в компактном формате, удобном для быстрой проверки.

Пример вывода команды capsh --print:

Current: = cap_net_bind_service,cap_dac_override+eip
Bounding set = cap_net_bind_service,cap_dac_override
Securebits: 00/0x0/0x0
secure-noroot: no (unlocked)
secure-no-suid-fixup: no (unlocked)
secure-keep-caps: no (unlocked)

Где:

  • Current — текущие возможности,
  • флаги +eip:
    • e (effective) — возможность активна в данный момент,
    • i (inheritable) — может быть унаследована дочерними процессами,
    • p (permitted) — возможность разрешена для использования процессом; процесс может активировать (e) только те возможности, которые есть в списке permitted.
  • Bounding set — потенциально доступные возможности; процесс может получить только те дополнительные возможности (например, через наследование от исполняемого файла), которые перечислены в bounding set,
  • Securebits — биты безопасности, эта секция управляет блокировкой изменений в наборах возможностей:
    • secure-noroot: no (unlocked) — если бы было yes (locked), то после сброса UID (например, при запуске от имени другого пользователя через --user в Docker) все capabilities были бы удалены из permitted и effective наборов. Если unlocked — capabilities сохранятся.
    • secure-no-suid-fixup: no (unlocked) — если locked, ядро не будет автоматически корректировать capabilities при изменении UID (например, при запуске SUID-программ). Обычно остаётся разблокированным.
    • secure-keep-caps: no (unlocked) — этот параметр определяет, сохранятся ли capabilities после смены пользователя. no означает, что при смене пользователя capabilities будут сброшены.

Вывод getpcaps 1:

1: cap_net_bind_service,cap_dac_override=eip

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

Примеры для популярных сервисов

Nginx

Для веб-сервера Nginx обычно требуется только возможность привязки к привилегированным портам (меньше 1024), а все остальные могут быть безопасно удалены:

docker run -d \
  --name nginx \
  --cap-drop=ALL \
  --cap-add=CAP_NET_BIND_SERVICE \
  -p 80:80 \
  -p 443:443 \
  nginx:alpine

Здесь CAP_NET_BIND_SERVICE позволяет процессу прослушивать порты 80 и 443 без прав root. Остальные возможности, такие как монтирование файловых систем или управление процессами, блокируются.

PostgreSQL

Для СУБД PostgreSQL могут быть нужны привилегии, связанные с управлением приоритетами:

docker run -d \
  --name postgres \
  --cap-drop=ALL \
  --cap-add=CAP_SYS_NICE \
  -e POSTGRES_PASSWORD=securepassword \
  postgres:15

CAP_SYS_NICE позволяет изменять приоритеты процессов для оптимизации производительности, остальные возможности безопасно удаляются.

Также иногда нужны:

  • CAP_IPC_LOCK — если используется mlock для предотвращения выталкивания shared buffers в swap,
  • CAP_SYS_RESOURCE — для установки лимитов (например, количества файловых дескрипторов).

Сетевые утилиты

Для работы сетевых диагностических утилит типа ping требуется CAP_NET_RAW:

docker run --rm \
  --cap-drop=ALL \
  --cap-add=CAP_NET_RAW \
  alpine ping -c 4 example.com

Однако используйте такие настройки только в доверенных окружениях, так как эта возможность может быть использована для сетевых атак.

Node.js и Python приложения

Большинство веб-приложений на Node.js или Python не требуют опасных привилегий, но могут нуждаться в базовых. Поэтому начните с --cap-drop=ALL:

docker run -d \
  --cap-drop=ALL \
  -p 3000:3000 \
  node:18-alpine \
  node app.js

При возникновении ошибок добавляйте новые привилегии, тестируя работу приложения после каждого изменения.

Как определить необходимые capabilities

Определение минимально необходимого для работы приложения набора привилегий — процесс, требующий системного подхода.

Запустите приложение с полными правами для тестирования:

docker run -d --cap-add=ALL --name test-container your-application

Проведите аудит используемых возможностей. Сначала получите PID основного процесса в контейнере:

PID=$(docker inspect test-container --format '{{.State.Pid}}')

И просмотрите текущие возможности процесса:

cat /proc/$PID/status | grep Cap

Также проанализируйте системные вызовы для определения необходимых привилегий, для этого понадобится утилита strace.

Установка strace в контейнер:

docker exec test-container apt-get update && apt-get install -y strace  # для Debian/Ubuntu

Или:

docker exec test-container apk add strace  # для Alpine

Однако установка strace в тестируемый контейнер изменяет его файловую систему, увеличивает образ и может повлиять на поведение. Если вы не хотите рисковать, используйте отдельный временный контейнер с инструментами для диагностики:

docker run -it --rm --pid=container:test-container --net=container:test-container ubuntu:22.04 bash -c "apt-get update && apt-get install -y strace && strace -p 1"

Этот временный контейнер будет использовать пространство имён и сетевое пространство целевого контейнера (test-container), поэтому strace -p 1 будет отслеживать процессы с PID 1 целевого контейнера.

Также можно использовать заранее подготовленные образы с инструментами мониторинга. 

Запустите запись системных вызовов:

docker exec test-container strace -f -o /tmp/strace.log your-process

Благодаря ключу -f, strace будет отслеживать не только основной процесс, но и все дочерние. Вывод будет сохранён в файл /tmp/strace.log внутри контейнера.

После этого постепенно удаляйте ненужные права, тестируя приложение между удалениями. В первую очередь удалите очевидно опасные привилегии:

docker run -d \
  --cap-drop=CAP_SYS_ADMIN \
  --cap-drop=CAP_SYS_MODULE \
  --cap-drop=CAP_SYS_PTRACE \
  --name test-iteration-1 \
  <your-image>:<tag>

И после этого постепенно удаляйте другие привилегии. Тестируйте функциональность после каждого изменения.

Рекомендации по безопасности:

  • Всегда начинайте с полного набора capabilities и постепенно уменьшайте его.
  • Ведите журнал изменений и тестовых результатов.
  • Используйте автоматизированные тесты для проверки функциональности.
  • Регулярно пересматривайте набор возможностей при обновлениях приложения.
  • Используйте статический анализ кода для выявления потенциально опасных операций.

Финальный, проверенный набор capabilities должен быть зафиксирован в Dockerfile (через --cap-drop и --cap-add в инструкциях) или в оркестраторе (например, в Docker Compose или Kubernetes Pod Spec), а не только передаваться через флаги командной строки при ручном запуске.

Читайте в блоге:

Loading spinner
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

Нужен VPS сервер?

Арендуйте мощный VPS сервер для ваших проектов! Быстрая настройка, высокая производительность и надежная поддержка 24/7. Начните прямо сейчас!

Что будем искать? Например,VPS-сервер

Мы в социальных сетях