Современные операционные системы стремятся минимизировать риски, связанные с выполнением привилегированных операций. В Linux долгое время основным механизмом разграничения доступа был деление пользователей на обычных и суперпользователя (root). Однако такая модель слишком груба: root имел неограниченные права, а все остальные — крайне ограниченные. Это приводило к необходимости запускать многие процессы от имени root, даже если им требовались всего пара привилегий. Чтобы решить эту проблему, в Linux был внедрён более гибкий механизм — capabilities.
Что такое capabilities в Linux
Capabilities (возможности) — это способ разделения прав суперпользователя на более мелкие, независимые привилегии. Идея состоит в том, чтобы позволить процессам выполнять только строго определённые действия, которые им действительно необходимы, не предоставляя полного доступа root.
Каждая capability отвечает за определённый тип привилегированного действия. Например, CAP_NET_BIND_SERVICE позволяет процессу слушать порты ниже 1024, а CAP_SYS_TIME — изменять системное время. Всего в ядре Linux определено более 40 capabilities, включая:
- 
CAP_CHOWN— изменение владельца файлов;
- 
CAP_SYS_ADMIN— очень широкая привилегия, включающая управление файловыми системами, монтирование и другие действия;
- 
CAP_NET_ADMIN— настройка сетевых интерфейсов;
- 
CAP_DAC_OVERRIDE— игнорирование правил доступа.
Эти возможности могут быть назначены как исполняемым файлам (через атрибуты безопасности), так и непосредственно процессам во время их выполнения.
Как capabilities применяются к процессам
Каждый процесс в Linux имеет набор capability-наборов, определяющих, какие действия он может совершать:
- 
Permitted — разрешённые возможности. Это максимальный набор capabilities, которые процесс может получить. 
- 
Effective — текущие активные возможности, то есть те, которые реально используются в данный момент. 
- 
Inheritable — набор возможностей, которые могут быть переданы дочерним процессам. 
- 
Bounding — верхняя граница всех возможных capabilities для процесса. 
- 
Ambient — используется в современных системах (начиная с Linux 4.3) для более удобной передачи возможностей между процессами без потери привилегий. 
По умолчанию, если обычный пользователь запускает процесс, у него нет никаких capabilities, кроме тех, что явно разрешены через механизмы вроде setcap.
Управление capabilities через утилиты
Одним из самых распространённых способов работы с capabilities является использование утилиты setcap. Она позволяет назначать определённые привилегии исполняемым файлам. Например:
Эта команда позволяет программе myserver слушать «низкие» порты (например, 80 или 443), не будучи запущенной от root.
Проверить текущие capability-привилегии файла можно с помощью:
Также capabilities можно устанавливать программно внутри самого процесса с использованием системных вызовов, таких как cap_set_proc() и cap_set_flag(), через libcap.
Ограничение capabilities для повышения безопасности
Хотя capabilities дают гибкость, ими нужно пользоваться осмотрительно. Самые частые ошибки — это назначение процессу слишком широких привилегий или использование опасных возможностей, таких как CAP_SYS_ADMIN, которая фактически эквивалентна root.
Вот несколько рекомендаций по безопасному использованию capabilities:
- 
Минимализм. Назначайте только те capabilities, которые действительно нужны. Лучше предоставить две узкие привилегии, чем одну широкую. 
- 
Анализ программы. Изучите, какие системные вызовы использует программа. Это поможет понять, какие именно возможности ей необходимы. 
- 
Изоляция процессов. Используйте capabilities совместно с другими механизмами безопасности: namespaces, seccomp, AppArmor или SELinux. 
- 
Использование ambient capabilities. Если программа порождает дочерние процессы, которым также нужны привилегии, лучше использовать ambient capabilities — это безопаснее, чем наследование через root. 
- 
Контроль bounding set. Сбросьте bounding set в начале запуска, чтобы гарантировать, что никакие возможности не будут получены «случайно». 
Также важно понимать, что capabilities не заменяют полностью традиционные модели контроля доступа, а являются лишь дополнением, позволяющим сделать права процессов более управляемыми.
Пример: запуск Nginx без root
Один из популярных примеров использования capabilities — запуск сетевых сервисов, таких как Nginx, на порту 80 без root-доступа. Обычно это требует запуска от root, потому что порты ниже 1024 зарезервированы. Однако можно разрешить Nginx использовать capability:
После этого можно настроить Nginx так, чтобы он не использовал root-пользователя, снизив потенциальные риски при эксплуатации уязвимостей в его коде.
Вывод
Механизм capabilities в Linux предоставляет мощный и гибкий инструмент разграничения привилегий. Он позволяет создавать более безопасные системы, минимизируя необходимость в запуске процессов от имени root. Однако его применение требует точного понимания сути каждой возможности, а также осмотрительности при их назначении.
Грамотное использование capabilities особенно важно в условиях современных угроз, где каждая лишняя привилегия может стать уязвимостью. Совмещая capabilities с другими мерами защиты, можно значительно повысить уровень безопасности системы, не теряя в функциональности.