...

Возможности Linux: безопасное и детальное распределение прав root

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

Центральные пункты

  • Мелкозернистый Вместо того чтобы предоставлять всеобъемлющие права: разбить права root на отдельные привилегии.
  • Возможности файлов Вместо Set-UID: привязать необходимые права непосредственно к бинарным файлам.
  • Наборы возможностей Настройка параметров: Permitted, Effective, Inheritable, Bounding.
  • Разделение привилегий: Строго разделять службы, инструменты и задачи.
  • Глубокая оборона: Дополнить возможности с помощью sudo, ролей и протоколов.

Зачем отключать права root?

Учетная запись с правами root предоставляет Полный доступ на уровне файлов и процессов, но именно это чревато серьезными ошибками. Достаточно одной неверной команды или эксплойта — и вся установка выйдет из строя. Поэтому я ограничиваю масштабные действия до самого необходимого, тем самым сокращая масштаб ущерба и время восстановления. Принцип минимальных прав позволяет поддерживать службы компактными и контролируемыми. Я отключаю прямой вход под пользователем root, использую ролевую систему и веду полные журналы.

Краткое объяснение возможностей Linux

Возможности Linux разбивают классические полномочия пользователя root на четко очерченные Привилегии. Каждый процесс получает только те компоненты, которые действительно необходимы для выполнения его задачи, например, привязку к портам ниже 1024 или отправку специальных сигналов. Таким образом я обхожу прежний подход «всё или ничего». Ядро управляет этими компонентами для каждого процесса и строго их реализует. Таким образом, контроль остаётся детализированным и прозрачным.

С технической точки зрения я связываю навыки либо с Процессы (по их наборам возможностей) или на Файлы (в виде расширенных атрибутов security.capability (бинарные файлы ELF). При execve()При запуске ядро объединяет возможности файла с наборами прав процесса: проще говоря, разрешенные возможности, взятые из атрибутов файла, а также наследуемые права вызывающего процесса объединяются в новый набор «Permitted» и — если это отмечено — одновременно активируются в наборе «Effective». Это позволяет избежать обходных путей Set-UID и обеспечивает прозрачность и контролируемость привилегий.

Понимание наборов возможностей в контексте процессов

Каждый процесс имеет несколько наборов прав, которые я целенаправленно управление. Набор «Permitted» определяет, чем процесс может обладать в принципе. Набор «Effective» определяет, что именно активно в данный момент. Набор «Inheritable» регулирует, какие привилегии могут передаваться дочерним процессам. Набор «Bounding» устанавливает жесткий верхний предел и не позволяет процессам выходить за его рамки.

Возможности работы в режиме ожидания и Securebits

Помимо известных наборов, есть ещё и Набор для создания атмосферы, который при execve() не истекает автоматически. Я использую его, когда непривилегированный процесс целенаправленно использует минимальные права в нескольких exec-независимо от уровня (например, при вызове внешних вспомогательных программ). Права «Ambient» учитываются в эффективных правах только в том случае, если вызываемый файл сам не устанавливает файловые возможности — таким образом я предотвращаю нежелательное повышение прав.

С помощью Securebits я регулирую детали переходов, например, может ли процесс после смены UID сохранить свои ранее установленные возможности (keepcaps) или же ему вообще запрещено получать новые привилегии (no_new_privs). На практике я настраиваю Securebits на строгий режим и иду на уступки в плане удобства, чтобы пресечь цепочки эксплойтов.

File Capabilities вместо Set-UID

Я заменяю бинарные файлы с атрибутом Set-UID на файловые возможности, чтобы снизить риск снижать. Вместо того чтобы предоставлять программе права суперпользователя, я просто устанавливаю необходимые права. Типичное изменение выглядит следующим образом: setcap 'cap_net_bind_service=+ep' /usr/bin/meinserver. С getcap -r / Я проверяю, в каких файлах содержатся навыки. Это заметно сокращает количество случаев эскалации.

Важно, чтобы файловые возможности применялись только к Бинарные файлы ELF действуют. Скрипты интерпретаторов (например, Python, Bash) не всегда надежно наследуют их. В таких случаях я инкапсулирую привилегированное действие в небольшую вспомогательную программу со статической проверкой или использую активацию через сокеты, чтобы моему сервису не приходилось самостоятельно устанавливать соединение. Кроме того, я слежу за правами доступа к файлам: возможности (capabilities) предоставляют особые права по отношению к ядру, но заменяют нет стандартные ACL или права доступа POSIX.

При копировании или упаковке навыки быстро теряются: cp без поддержки XATTR, неправильно установленные umask или удалить артефакт сборки из файловой системы без расширенных атрибутов security.capability по умолчанию. Поэтому я работаю с соблюдением воспроизводимости и использую: cp --preserve=xattr ..., tar --xattrs, rsync -X. При сборке пакетов я явно задаю файловые возможности в скрипте установки, тестирую установку в чистой виртуальной машине и проверяю getcap в CI.

Разделение привилегий с использованием реалистичных сценариев

Веб-серверу требуется доступ к портам 80/443, но не к модулям ядра или перезагрузкам системы, поэтому я устанавливаю CAP_NET_BIND_SERVICE и больше ничего. Агент резервного копирования может читать и записывать файлы, но не может изменять сетевую конфигурацию. Инструмент мониторинга получает права на чтение показателей, но не имеет прав на их изменение. Такое распределение прав позволяет локализовать атаки, не давая им распространиться на всю систему. Именно это разделение обеспечивает управляемость служб и сдерживает ошибки в настройках.

Использование в сочетании с sudo и ролями

Возможности не заменяют аккуратную Структура ролей, они их дополняют. Я строго ограничиваю права sudo, использую полные пути к командам и избегаю общих правил, таких как „ALL=(ALL) ALL“. Каждое предоставление прав я фиксирую в журнале. Группы объединяют сферы ответственности, а возможности устанавливают технические ограничения в процессах. Таким образом формируются чёткие сферы ответственности без избыточных прав.

Распространенные ошибки и передовой опыт

  • Не использовать сокращение CAP_SYS_ADMIN: Это право представляет собой общий термин. Я заменяю его более конкретными вариантами (например,. CAP_SYS_CHROOT, CAP_SYS_TIME, CAP_SYS_NICE) или вообще откажись от этого.
  • Права доступа к файлам остаются неизменными: Возможности не всегда позволяют обойти DAC. Без CAP_DAC_OVERRIDE Ядро по-прежнему учитывает биты владельца и режима доступа. Поэтому я по-прежнему предоставляю права на чтение в минимальном объеме.
  • Отверждение по трассу: Если я назначаю бинарному файлу файловые возможности, это предотвращает подделку PATH (абсолютные пути в sudoers, ограниченные права на запись в каталогах, входящих в путь поиска).
  • Пускайте рано и часто: Процессы могут запускаться с более широкими правами, чем необходимо. Я удаляю лишние права сразу после выполнения критического шага (prctl()/libcap) и установить no_new_privs, где это возможно.
  • Ограничить наследование: Я стараюсь, чтобы наборы «Inheritable» и «Ambient» оставались небольшими. Дочерние процессы не должны открывать новые двери.
  • Проверка конвейера сборки и развертывания: Я подтверждаю, что security.capability сохраняется, и ни один из этапов подготовки (слои контейнеров, NFS, сканер артефактов) не удаляет XATTR.

Обзор основных возможностей и рисков

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

Возможности Назначение Риск Пример
CAP_NET_BIND_SERVICE Привязка к портам с номерами меньше 1024 От низкого до среднего Веб-сервер на портах 80/443
CAP_SYS_BOOT Перезагрузить систему Высокий Запланированная перезагрузка
CAP_SYS_MODULE Загрузка/удаление модулей ядра Очень высокий Управление драйверами
CAP_SYS_ADMIN Разнообразные административные операции Очень высокий Различные работы по техническому обслуживанию
CAP_SETUID / CAP_SETGID Сменить UID/GID От среднего до высокого Смена полномочий в ходе службы

Помимо таблицы, я сейчас оцениваю CAP_SYS_PTRACE (отладка процессов), CAP_NET_ADMIN (настройка параметров сети) и CAP_DAC_OVERRIDE (обход ограничений доступа к файлам) — крайне критично. Часто существуют шаблоны, позволяющие обойти эти права: использование специальных конечных точек для сбора метрик вместо слежения за процессами, активация сокетов или перенаправление портов вместо прав привязки, а также четко заданные права доступа к файлам вместо общего обхода DAC.

Развертывание в контейнерах и хостинг

В многопользовательских средах я считаю, что навыки должны быть радикально маленький и предотвращаю наследование в дочерних процессах. Контейнеры получают значительные преимущества, как только набор границ (Bounding-Set) становится жестко заданным. Я сочетаю это с изолированными пространствами файловой системы и процессов. Для обзора подходов к изоляции мне помогает это введение в Изоляция процессов. Таким образом, службы остаются раздельными, даже если какое-то приложение начинает работать нестабильно.

На практике я по умолчанию настраиваю контейнеры на режим „выбрасывать всё, добавлять по выбору“: --cap-drop=ALL --cap-add=NET_BIND_SERVICE для веб-сервисов, без прав на монтирование, без SYS_ADMIN. В оркестрированных средах я централизованно управляю профилем и проверяю его в политиках. Важно: я не полагаюсь на файловые возможности в образе, а назначаю права во время выполнения в оркестраторе — это обеспечивает воспроизводимость и возможность аудита.

Взаимодействие с SELinux и AppArmor

Возможности определяют, что разрешено процессу, а профили MAC — к чему он имеет доступ, и эти два компонента гармонично взаимодействуют хорошо. Я устанавливаю узкие ограничения (Capabilities) и позволяю SELinux или AppArmor ограничивать доступ к файлам и сокетам. Таким образом создается многоуровневая защита, которая ставит перед эксплойтами несколько препятствий. Быстрое сравнение я нахожу здесь: SELinux против AppArmor. Таким образом, скомпрометированный сервис остается изолированным и не может нанести столь значительный ущерб.

Практика: действуйте пошагово

Я начну с анализа всех служб и их Требования. Затем я удаляю ненужные бинарные файлы с атрибутом Set-UID или заменяю их целевыми возможностями файлов. Я настраиваю sudo с максимальной строгостью и документирую каждую запись. Я присваиваю задачи ролям и группам и свожу права к минимуму. Затем я провожу тестирование под нагрузкой и проверяю записи в журналах на наличие неожиданных отказов.

Краткий контрольный список помогает мне в переходе:

  • Зафиксировать в письменной форме требования для каждой службы (только то, что действительно необходимо).
  • Составить перечень существующих особых прав (find / -perm -4000, getcap -r /).
  • Целенаправленная замена: отказ от Set-UID, установка файловых возможностей, своевременное снятие прав.
  • Закрыть наследование: оптимизировать ограничивающее множество, минимизировать наследуемые/окружающие переменные.
  • Обеспечение безопасности профилей systemd/контейнеров (CapabilityBoundingSet=, NoNewPrivileges=yes).
  • Провести тестирование под нагрузкой, проверить журналы и записи аудита, задокументировать исключения.

Мониторинг, пространства имён и непрерывные аудиты

Я отслеживаю файлы журналов, сигналы тревоги и системные вызовы, чтобы немедленно реагировать на нежелательные действия выделяться. Я регулярно проверяю изменения в наборах прав, правилах sudo и ролях. Там, где это целесообразно, я дополнительно разделяю рабочие нагрузки с помощью механизмов изоляции ядра. Хорошей отправной точкой послужит этот обзор по Пространства имён и Cgroups. Так я своевременно обнаруживаю отклонения и поддерживаю чистоту в помещении.

В повседневной жизни я использую простые проверки: capsh --print покажи мне текущий набор навыков, getpcaps перечисляет процессуальные права и в /proc//status я читаю CapEff, CapPrm, CapBnd. С auditd я отслеживаю изменения статуса возможностей (например, правило на capset), сопоставляю события с развертываниями и настраиваю оповещения, если внезапно появляются расширенные права. В сложных случаях мне помогает strace -e capget,capset, чтобы выявить манипуляции с правами доступа.

Практические примеры использования systemd и контейнеров

Многие службы я запускаю в виде модулей systemd и инкапсулирую в них права доступа:

  • CapabilityBoundingSet=CAP_NET_BIND_SERVICE сокращает доступное правовое окно до самого необходимого.
  • AmbientCapabilities=CAP_NET_BIND_SERVICE предоставляет службе право подключаться к портам 80/443 без использования файловых возможностей.
  • NoNewPrivileges=yes препятствует последующему расширению прав.
  • Пользователь=, Группа=, ProtectSystem=strict, PrivateTmp=yes завершают процесс изоляции.

В контейнерах я запускаю процессы с минимально возможным набором ресурсов: docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE --read-only. Для краткосрочных заданий я использую в образе возможности, связанные со временем выполнения, а не с файлами, чтобы сборки оставались воспроизводимыми, а права доступа привязывались к конкретной среде.

Конкретные примеры миграции из практики

  • ping без Set-UID: Вместо setuid root я ставлю setcap 'cap_net_raw=+ep' /bin/ping. Таким образом, любой пользователь может открывать ICMP-сокеты без полных прав root. Я регулярно проверяю с помощью getcap /bin/ping, сохранился ли этот атрибут.
  • Веб-сервис на портах 80/443: Я запускаю свою службу в режиме непривилегированного пользователя и передаю только cap_net_bind_service. Если сервис и так находится за обратным прокси-сервером, в качестве альтернативы я могу привязать его там к портам 80/443 и использовать внутренний порт с высоким номером — без каких-либо дополнительных навыков.
  • Смена сторон в судебном процессе: Для утилит, которым на короткое время требуются расширенные права (например, для установки уровней приоритета), я устанавливаю cap_sys_nice, выполни действие как можно раньше, а затем сними эту способность. Я стараюсь избегать постоянного расширения прав.

Ограничения и альтернативы

Не во всех случаях применения требуются специальные возможности. Зачастую существуют безопасные альтернативы с меньшим риском:

  • Активация сокета: Служба инициализации (например, systemd) открывает сокеты с привилегиями и передаёт их процессу. В таком случае моей службе не требуются права Bind.
  • Перенаправление портов: С помощью правил брандмауэра я перенаправляю порты 80/443 на высокий порт. Сервис остается без привилегий, поведение системы не меняется.
  • Непривилегированные порты низкого уровня: Если это целесообразно, я могу повысить порог для непривилегированных портов. Однако это расширяет возможности для всех процессов — я тщательно взвешиваю риски и удобство.
  • Небольшие помощники вместо универсальных устройств: Лучше крошечный, прошедший аудит бинарник с ровно одной способностью, чем огромный монолит с обширным набором прав.

Краткое резюме

С Возможности Linux Я разбиваю права root на небольшие, легко контролируемые привилегии. Файловые возможности заменяют рискованные бинарные файлы с атрибутом Set-UID и снижают последствия атаки. В сочетании со строгими правилами sudo, ролями и профилями MAC создается многоуровневая защита с четкими границами. Наборы ограничений (Bounding Sets) и наследуемых прав (Inheritable Sets) ограничивают наследование прав и удерживают процессы в нужном русле. Такой подход позволяет заметно сократить уязвимости и свести административную нагрузку к минимуму.

Текущие статьи

Безопасно настроенный сервер Linux с гранулярными правами root в центре обработки данных
Безопасность

Возможности Linux: безопасное и детальное распределение прав root

Возможности Linux (Capabilities) разделяют права root на более мелкие привилегии. Узнайте, как модель возможностей укрепляет безопасность вашего сервера и обеспечивает разделение привилегий в системах Linux.

Серверные стойки Linux с концепциями безопасности для SELinux и AppArmor
Безопасность

SELinux против AppArmor — сравнение концепций безопасности для современных серверов Linux

Подробное сравнение SELinux и AppArmor: узнайте, какая концепция безопасности для Linux, изоляции контейнеров и укрепления безопасности серверов лучше всего подходит для вашей инфраструктуры.

Сервер Linux с включенной песочницей Seccomp и защищенным ядром
Безопасность

Seccomp в Linux: целенаправленное ограничение возможностей приложений для повышения безопасности

Seccomp Linux — это ключевой компонент безопасности ядра. Узнайте, как режим безопасного вычисления (Secure Computing Mode) ограничивает системные вызовы, изолирует контейнеры в «песочнице» и эффективно защищает ваши рабочие нагрузки.