Что такое capabilities Linux?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Capabilities в Linux: концепция привилегированного доступа нового поколения
В традиционной модели безопасности Linux используется бинарная система привилегий: процесс либо обладает полными правами суперпользователя (root, UID 0), либо работает с ограниченными правами обычного пользователя. Это "всё или ничего" создавало значительные риски безопасности, поскольку любая уязвимость в программе, запущенной от root, могла привести к полному компрометированию системы. Capabilities (возможности) были введены в ядре Linux, начиная с версии 2.2, как механизм тонкого дробления привилегий суперпользователя на отдельные, независимые права.
Суть и философия Capabilities
Capabilities — это отдельные права на выполнение конкретных привилегированных операций. Вместо одного статуса "root" существует множество (около 40) различных способностей, таких как право изменять системное время, работать с сетевыми сокетами, загружать модули ядра или игнорировать проверки прав доступа к файлам (DAC). Процессу или исполняемому файлу можно назначить строго необходимый для его работы набор capabilities, минимизируя тем самым поверхность атаки.
Типы Capabilities и их хранение
Существует три набора capabilities для каждого процесса, хранящиеся в структуре задач ядра (task_struct):
- Effective (E): Фактически используемые в данный момент возможности. Именно этот набор проверяется ядром при попытке выполнения привилегированной операции.
- Permitted (P): Максимальный набор возможностей, которые процесс может иметь. Процесс может добавить capability из этого набора в Effective, но не может добавить то, чего нет в Permitted.
- Inheritable (I): Набор возможностей, которые могут быть унаследованы при выполнении
execve()(запуске новой программы). Чтобы capability действительно перешла в Permitted набор нового процесса, она должна быть и в Inheritable наборе родителя, и в Inheritable наборе исполняемого файла (см. ниже).
Для исполняемых файлов также определены два набора capabilities (хранятся в расширенных атрибутах файла security.capability):
- Inheritable (I): "Маска наследования". Определяет, какие capabilities из Inheritable набора процесса могут перейти в Permitted набор нового процесса после
execve. - Permitted (P): Набор capabilities, которые автоматически добавляются в Permitted набор процесса при запуске файла, независимо от возможностей родительского процесса.
- Effective (E): На самом деле это один бит (флаг), а не набор. Если он установлен, ядро автоматически поднимает все capabilities из нового Permitted набора в Effective набор после
execve. Если сброшен — Effective набор после запуска очищается, и процесс должен вручную поднять нужные capabilities (обычно с помощьюcapset()).
Практическое использование и примеры
Управление capabilities осуществляется с помощью утилит setcap и getcap из пакета libcap, а также программного интерфейса libcap в коде.
Пример 1: Выдача права на использование "привилегированных" портов (ниже 1024) демону без запуска от root. Ранее для этого требовался setuid root.
# Установка capabilities для бинарника my_web_server
# CAP_NET_BIND_SERVICE позволяет биндиться на порты <1024
# CAP_SETPCAP условно, может потребоваться для управления своими же capabilities
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/my_web_server
# Проверка установленных capabilities
getcap /usr/local/bin/my_web_server
# /usr/local/bin/my_web_server = cap_net_bind_service+ep
Теперь пользователь www-data может запустить этот сервер, и он сможет слушать 80-й порт, не имея никаких других прав root.
Пример 2: Написание программы, которая использует capabilities через libcap. Программа временно повышает привилегию, выполняет действие и опускает её.
#include <sys/capability.h>
#include <unistd.h>
#include <stdio.h>
int main() {
cap_t caps = cap_get_proc(); // Получаем текущие capabilities
cap_value_t cap_list[] = {CAP_SYS_TIME};
// Добавляем CAP_SYS_TIME в Effective и Permitted наборы
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_SET) == -1 ||
cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_SET) == -1) {
perror("cap_set_flag");
return 1;
}
// Применяем изменения к процессу
if (cap_set_proc(caps) == -1) {
perror("cap_set_proc");
return 1;
}
cap_free(caps);
// Теперь мы можем изменить системное время (здесь просто пример)
printf("Процесс имеет CAP_SYS_TIME.\n");
// Сбрасываем capability из Effective набора (принцип наименьших привилегий)
caps = cap_get_proc();
if (cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR) == -1) {
perror("cap_set_flag clear");
return 1;
}
cap_set_proc(caps);
cap_free(caps);
printf("Привилегия CAP_SYS_TIME опущена из Effective набора.\n");
return 0;
}
Компиляция и запуск:
gcc -o cap_test cap_test.c -lcap
sudo setcap 'cap_sys_time=p' cap_test # Даем только Permitted, без Effective
./cap_test
Важность для DevOps и контейнеризации
Capabilities являются краеугольным камнем безопасности контейнеров (Docker, Kubernetes). По умолчанию Docker запускает контейнеры с сильно урезанным набором capabilities (например, удалены CAP_SYS_ADMIN, CAP_NET_RAW, CAP_SYS_MODULE). Это предотвращает множество атак даже в случае компрометации процесса внутри контейнера.
- Docker: Управление через флаги
--cap-addи--cap-drop.# Запуск контейнера с минимальными привилегиями docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx # Опасный, но иногда необходимый режим (дает все capabilities) docker run --privileged my_app - Kubernetes: Задание в SecurityContext пода или контейнера.
securityContext: capabilities: add: ["NET_ADMIN"] drop: ["ALL"]
Ключевые преимущества и выводы
- Снижение рисков: Принцип наименьших привилегий (Least Privilege) реализуется на уровне процесса.
- Гранулярность: Точный контроль над тем, что именно может делать процесс.
- Наследование: Четкие правила передачи прав дочерним процессам.
- Независимость от UID: Права привязаны к исполняемому файлу и процессу, а не только к пользователю.
- Фундамент для контейнеров: Без capabilities современная изоляция workloads была бы гораздо менее безопасной.
Таким образом, capabilities — это эволюция модели безопасности Linux, позволяющая уйти от монолитных привилегий root в сторону безопасной, контролируемой и детализированной системы прав, что абсолютно необходимо для построения отказоустойчивых и безопасных инфраструктур в парадигме DevOps.