Линукс
Linux: Права доступа
Третья часть серии о Linux для DevOps и DevSecOps – разбираем права доступа, модель UGO, биты rwx, числовое и символьное представление, chmod и chown.
Введение
Продолжаем серию рубрики Linux. В прошлой серии разобрали пользователей и группы – UID, GID, /etc/passwd. Теперь разберём что ядро делает с этими числами когда процесс пытается открыть файл или войти в директорию. Про права доступа легко выучить команды – chmod 755, chown user file – но не понимать что происходит под капотом. Тогда начинаются странные ситуации: «я же владелец, почему Permission denied?». Цель этой статьи – дать модель, а не только набор команд.
Вся статья построена на практике: каждый раздел можно пройти руками. Для большинства примеров достаточно обычного пользователя, для части нужен sudo. Где нужен – отмечено явно. Серия в основном под Ubuntu/Debian.
В конце статьи будет бонус который даст вам возможность изучить права доступа в Linux ещё доступнее и возможно проще.
1. Что такое права доступа и зачем они нужны
Linux – многопользовательская система. На одной машине одновременно работают процессы от разных пользователей: nginx читает файлы сайта, postgres работает со своими данными, разработчик ivan пишет код в своём каталоге. Без изоляции любой мог бы читать чужие ключи SSH, удалять чужие файлы, подменять конфиги сервисов.
Права доступа – механизм изоляции. Каждый файловый объект несёт метаданные: кто владелец, какая группа, кто что может делать. Метаданные хранятся в inode – структуре файловой системы которая описывает файл. Важно понимать: содержимое файла и его метаданные (включая права) хранятся раздельно. Когда вы делаете ls -la – вы читаете именно inode, а не сам файл.
Посмотрим на конкретный пример. Файл /etc/shadow хранит хеши паролей всех пользователей:
Права гарантируют что читать его может только root и члены группы shadow. Обычный пользователь – нет. Разберём эту строку полностью, слева направо.
| Часть | Что означает |
|---|---|
-rw-r----- | тип файла и биты прав (разберём ниже) |
1 | количество жёстких ссылок на файл |
root | владелец файла |
shadow | группа-владелец файла |
1478 | размер в байтах |
апр 16 12:03 | дата последнего изменения |
/etc/shadow | путь к файлу |
2. Модель UGO – три класса доступа
Стандартная модель Linux делит всех на три класса относительно конкретного файла.
U – User (владелец). Один конкретный пользователь. Когда создаёте файл – автоматически становитесь его владельцем. G – Group (группа). Одна конкретная группа. По умолчанию – primary group пользователя который создал файл. O – Others (остальные). Все кто не попал в первые два класса.
Для каждого из трёх классов устанавливается свой набор прав. Вот как это выглядит в выводе ls -la:
Первый символ – тип файла:
| Символ | Тип |
|---|---|
- | обычный файл |
d | директория |
l | символическая ссылка |
b | блочное устройство |
c | символьное устройство |
p | именованный канал (pipe) |
s | сокет |
Следующие 9 символов – три блока по три бита для U, G и O. Вернёмся к /etc/shadow:
Каждый файл имеет ровно одного владельца и ровно одну группу – не двух, не список. Это ограничение стандартной модели UGO. Для более гибкого управления существуют ACL – разберём их в разделе 9.
3. Биты rwx – что они означают
Три бита в каждом блоке: r – read, w – write, x – execute. Установлен бит – операция разрешена. Сброшен (дефис) – запрещена. Смысл битов различается для файлов и директорий.
Для файлов
| Бит | Что разрешает |
|---|---|
r | читать содержимое (cat, less, cp) |
w | изменять содержимое (редакторы, echo >>) |
x | запускать как программу |
Для директорий
Здесь важно не путать – директория это тоже файл, просто специального типа. Биты работают иначе.
| Бит | Что разрешает |
|---|---|
r | читать список файлов внутри (ls) |
w | создавать и удалять файлы внутри |
x | входить (cd) и обращаться к файлам по имени |
На директориях бит х (проход) нужен, чтобы в дальнейшем войти через cd или обратиться к файлу по пути. r без x будет парадоксом, где список файлов через ls будет видно а открыть нельзя, поэтому r и x на директориях почти во многих случаях ставятся вместе.
4. Числовое и символьное представление
Существует два способа записывать права, и оба используются в реальной работе. Разберём оба.
Числовое (восьмеричное)
Каждый бит имеет числовое значение:
Чтобы получить число для класса – складываем биты:
Итоговые права – три цифры, по одной для U, G, O:
777 означает что любой пользователь на системе может читать, изменять и запускать файл. На сервере где работают несколько пользователей – это дыра. Особенно опасно если это скрипт который запускается по cron от root – любой сможет подменить его содержимое. Используйте с осторожностью.
Шпаргалка по типовым комбинациям:
| Права | Символьно | Когда применять |
|---|---|---|
644 | rw-r--r-- | Обычные файлы, конфиги |
755 | rwxr-xr-x | Исполняемые файлы, директории |
600 | rw------- | Приватные ключи SSH, секреты |
640 | rw-r----- | Конфиги с паролями – группа читает, others нет |
700 | rwx------ | Домашняя директория сервисного пользователя |
750 | rwxr-x--- | Директории сервисов |
777 | rwxrwxrwx | Почти никогда – проблема безопасности |
Символьное
Удобно когда нужно добавить или убрать один бит не трогая остальные – не надо держать в голове итоговое число. Синтаксис: [кто][операция][что].
Кто: u – владелец, g – группа, o – остальные, a – все сразу (u+g+o).
Операция: + – добавить, - – убрать, = – установить точно (остальные биты сбросятся).
Когда что удобнее: числовой – когда знаешь точное итоговое состояние. Символьный – когда хочешь изменить один бит не затрагивая остальные.
Особый случай: +X (заглавная)
+x (строчная) ставит бит execute на всё подряд – и на файлы, и на директории. +X (заглавная) её можно назвать умнее: она ставит execute только там, где это имеет смысл – на директории всегда, на файлы только если у кого-то из классов уже стоит x.
Пример где можно применить: для рекурсивной установки прав.(Это безопаснее и правильнее чем потом чистить лишние биты через find.)
5. chmod – изменение прав
chmod (от change mode) – команда для изменения прав доступа.
Здесь есть типичная ловушка при настройке веб-серверов. Многие делают так:
Эта команда поставит 755 на абсолютно все объекты – и директории, и файлы. Для директорий 755 нормально, им нужен x чтобы в них можно было входить. Но для файлов это означает что .html, .css, .jpg становятся исполняемыми – а этого не должно быть. Правильный способ – разделить файлы и директории:
После этого права будут корректные: директории – 755, файлы – 644, без лишнего x. Главное: не ставить права «на глаз» – всегда думайте кому реально нужен доступ.
6. chown и chgrp – смена владельца и группы
chown (от change owner) меняет владельца файла, группу, или оба сразу. chgrp (от change group) меняет только группу – по сути то же что chown :group, просто отдельная команда.
Обычный пользователь может поменять группу файла только на одну из своих собственных групп. Поменять владельца на другого пользователя – только root. Без этого ограничения можно было бы «подарить» вредоносный файл с SUID другому пользователю – и это стало бы простым способом эскалации привилегий.
7. Как ядро принимает решение о доступе
Это самый важный раздел статьи. Команды можно выучить, но без понимания алгоритма поведение системы будет казаться непредсказуемым. Особенно когда видишь Permission denied там где не ожидаешь.
7.1 Real vs Effective UID
Когда пользователь запускает программу, у процесса есть несколько идентификаторов. RUID (Real UID) – кто фактически запустил процесс. Не меняется в течение жизни процесса. EUID (Effective UID) – от чьего имени процесс работает прямо сейчас. Именно его проверяет ядро при обращении к файлу.
В большинстве случаев RUID == EUID. Но это различие становится важным при SUID – разберём в следующем разделе.
Четыре числа в строке: Real UID, Effective UID, Saved UID (нужен для временного переключения прав), Filesystem UID (используется при проверке доступа к файлам – в большинстве случаев совпадает с EUID). Для понимания прав доступа ключевой – второй, EUID.
7.2 Алгоритм проверки прав
Когда процесс обращается к файлу, ядро проверяет права строго по порядку и останавливается на первом совпадении:
- Если EUID = 0 (root) → доступ почти всегда разрешён
- Если EUID совпадает с владельцем файла → используются права владельца
- Если группа процесса (EGID или дополнительные группы) совпадает с группой файла → используются права группы
- Во всех остальных случаях → используются права для остальных (others)
Система не комбинирует права – она берёт только один подходящий вариант и на этом заканчивает проверку.
7.3 Права не суммируются
Частая ловушка с которой сталкиваются многие. Допустим есть файл:
Пользователь ivan является владельцем и одновременно входит в группу developers:
Но если ivan попробует прочитать файл – получит Permission denied. Почему? Ядро проверило: EUID процесса совпадает с UID файла – совпадение на шаге 2. Применило биты owner – ---. Остановилось. Биты group rwx даже не рассматривались. ivan является владельцем, но у владельца нет прав. Группа имеет полный доступ – но до неё проверка не дошла.
Решение – дать владельцу права явно:
Уточнение: пример выше демонстрирует механику проверки прав ядром, а не реальную схему работы с группами. Ситуация ----rwx--- на файле, где владелец намеренно без прав, надуманная и в реальной практике почти не встречается.
Зачем тогда нужны группы?
Главная задача групп – дать одинаковые права произвольному набору пользователей без того, чтобы менять права на каждом файле вручную. Это работает именно потому что проверка group-битов срабатывает когда пользователь не является владельцем файла.
Примерный сценарий: команда разработчиков работает с общим проектом.
Теперь ivan – владелец (rwx), все члены группы developers – читают и входят (r-x), остальные – ничего. Когда нужно добавить нового разработчика – просто usermod -aG developers newuser, и он сразу получает нужный доступ. Группы становятся особенно полезными в связке с SGID на директории (раздел 8): новые файлы автоматически наследуют группу директории, и всем членам группы не нужно думать о правах при создании файлов.
7.4 root и права
root (EUID=0) обходит проверку UGO для большинства операций – может читать любой файл, писать в любой файл независимо от прав. Но есть одно исключение: бит execute. Даже root не может запустить файл если ни у кого не установлен x:
Чтобы запустить – сначала chmod +x script.sh, потом sudo ./script.sh. Это защита от случайного запуска: если x не установлен, файл не является исполняемым ни для кого, включая root.
8. Специальные биты – SUID, SGID, Sticky bit
Помимо стандартных rwx существуют три специальных бита. Каждый работает по-разному в зависимости от того – установлен он на файл или на директорию.
SUID (Set User ID)
При запуске файла с SUID процесс получает EUID = UID владельца файла, а не UID пользователя который его запустил. Пример – команда passwd. Обычный пользователь должен иметь возможность сменить свой пароль, а значит записать новый хеш в /etc/shadow. Но /etc/shadow доступен только root. SUID решает эту проблему: /usr/bin/passwd принадлежит root и имеет SUID – при запуске процесс временно получает EUID=0 и может писать в shadow.
s вместо x в блоке владельца – SUID установлен. Заглавная S (без x) означает что SUID установлен но бит execute при этом не установлен – это подозрительная ситуация которой обычно не должно быть.
SUID-бинарники – популярная цель при атаках на повышение привилегий. Если на стандартной утилите вроде vim, find или bash внезапно появился SUID – это серьёзный повод для расследования. Регулярно проверяйте список SUID-файлов и сравнивайте с эталоном.
Эталон – это список SUID-файлов, снятый в заведомо чистом состоянии системы (сразу после установки или после проверенного аудита). При следующих проверках вы сравниваете текущий список с ним и видите, что появилось нового.
SGID (Set Group ID)
SGID работает по-разному для файлов и директорий. На файл: процесс получает EGID = GID группы файла – аналог SUID но для группы. Используется редко. На директорию: все файлы и поддиректории созданные внутри автоматически наследуют группу этой директории, а не primary group создателя. Это ключевой механизм для совместной работы. В качестве примера возьмём несколько разработчиков которые работают с одной директорией. Без SGID каждый создаёт файлы со своей primary group – другие не могут их редактировать даже если входят в нужную группу. С SGID все файлы автоматически получают группу директории и все члены группы могут работать с ними без лишних телодвижений.
Sticky bit
Sticky bit решает конкретную проблему: если у пользователя есть право w на директорию – он может удалить из неё любой файл, даже чужой. На директорию: пользователь может удалить файл только если он является владельцем файла или владельцем директории. Просто иметь w на директорию – недостаточно. Пример – /tmp, где директория доступна на запись всем, но никто не должен удалять чужие файлы:
t вместо x в блоке others – sticky bit установлен.
Сводная таблица
| Бит | Числовой | Символьный | На файл | На директорию |
|---|---|---|---|---|
| SUID | 4000 | u+s | EUID = UID владельца файла | Нет эффекта |
| SGID | 2000 | g+s | EGID = GID группы файла | Новые файлы наследуют группу директории |
| Sticky | 1000 | +t | Нет эффекта | Удалить файл может только его владелец |
Специальные биты идут первой цифрой в четырёхзначной записи:
9. ACL – когда стандартных прав недостаточно
Стандартная модель UGO имеет фундаментальное ограничение: один владелец и одна группа. Что если нужно дать доступ двум разным пользователям с разными правами? Например, пользователь maria должна читать и писать файл, пользователь sergei – только читать, а все остальные – ничего. В UGO это не реализовать. ACL (Access Control Lists) решают эту задачу – они позволяют прописать права для произвольного количества пользователей и групп на один объект.
Для начала проверим что пакет установлен:
9.1 Просмотр ACL
Пока ACL не установлены – вывод совпадает с обычными правами. Как только добавляем ACL-запись, в выводе ls -la появляется символ + в конце строки прав:
9.2 Установка ACL
После добавления ACL для maria – getfacl покажет дополнительные строки:
9.3 Маска
Маска – это максимально возможные эффективные права для всех ACL-записей, кроме владельца и others. Если маска r-x, то даже ACL с rwx реально даст только r-x. Маска появляется автоматически при добавлении первой ACL-записи и расширяется когда вы добавляете записи с большими правами. Можно задать явно:
9.4 ACL по умолчанию – важный момент
Без флага -d ACL применяется только к уже существующим файлам. Новые файлы созданные в директории его не наследуют. Это частая ошибка – настроил ACL на директорию, а файлы которые потом создаются внутри его не получают.
Правильный паттерн – всегда два вызова:
10. umask – права по умолчанию при создании файлов
Когда создаётся новый файл или директория – система не даёт максимально возможные права, а вычитает из них маску. Это и есть umask. Максимальные права при создании: файл – 666 (execute никогда не ставится автоматически), директория – 777.
Строго говоря umask работает как побитовая операция исключения, а не простое вычитание. Разница проявляется если у вас нестандартные значения: например, 666 минус 033 математически даст 633, но побитовое исключение даст 644. Для стандартных значений (022, 027, 077) простое вычитание даёт верный результат и удобнее для понимания.
Типичные значения
| umask | Файлы | Директории | Когда применять |
|---|---|---|---|
022 | 644 | 755 | Стандарт – публичный доступ на чтение |
027 | 640 | 750 | Усиленный – others вообще без доступа |
077 | 600 | 700 | Параноидальный – только владелец |
Где настраивается
Бонус и Заключение
Мы рассмотрели всё начиная от базовой модели UGO и битов rwx до алгоритма принятия решений ядром, специальных битов и ACL. Отдельно хочу поделиться полезным материалом на YouTube от Дмитрия с заданиями для самостоятельной отработки навыков, очень полезно тем, кто только начинает учить Linux.
- Урок 12 – Управление пользователями и группами
- Урок 13 – Избирательные права доступа (DAC) над файлами
- Урок 14 – Избирательные права доступа (DAC) над каталогами
Увидимся в следующей части серии!
