права доступа глубже
За пределами rwx: setuid заставляет бинарник выполняться от имени владельца; setgid на каталоге принудительно наследует группу; sticky на /tmp не даёт удалять чужие файлы. umask отсекает права по умолчанию, а POSIX ACL дают доступ конкретным пользователям.
Ты уже знаешь rwx. Но потом видишь /usr/bin/passwd с правами -rwsr-xr-x — буква s вместо бита выполнения это не опечатка. Или создаёшь общий каталог /var/project/, а файлы упорно оказываются во владении первичной группы создателя, и половина команды не может их изменить. Или пентестер говорит: «вот твой путь повышения привилегий — этот setuid-бинарник». Или аудит безопасности помечает мировой каталог без sticky-бита — и ты не сразу понимаешь угрозу. Модель rwx из девяти битов — это только пол; специальные биты и ACL выше неё — там живут реальные системы.
После этого урока ты сможешь объяснить, что делают биты setuid, setgid и sticky (с реальной моделью угроз), вычислить эффективные права из umask и предоставить доступ конкретному пользователю через POSIX ACL, когда членства в группе недостаточно.
Бит setuid заставляет бинарник выполняться от имени его владельца, а не вызывающего. Именно так непривилегированные пользователи могут менять собственные пароли: /usr/bin/passwd принадлежит root и имеет бит setuid, поэтому когда alice запускает его, effective UID процесса становится 0 (root), что позволяет записывать в /etc/shadow.
# Видим setuid в действии
ls -l /usr/bin/passwd
# -rwsr-xr-x 1 root root 59976 Feb 6 16:54 /usr/bin/passwd
# ^-- строчная 's' на месте execute-бита владельца = setuid + исполняемый
# заглавная 'S' означала бы setuid без права выполнения (бесполезно)
# Восьмеричное значение: setuid — бит 4 в старшем полубайте
stat -c '%a %n' /usr/bin/passwd
# 4755 /usr/bin/passwd
# 4 = setuid, 7 = rwx (владелец), 5 = r-x (группа), 5 = r-x (остальные)
# Найти все setuid-root бинарники в системе
find /usr/bin /usr/sbin /bin /sbin -perm -4000 -ls 2>/dev/null
# -rwsr-xr-x root /usr/bin/passwd
# -rwsr-xr-x root /usr/bin/sudo
# -rwsr-xr-x root /usr/bin/su
# -rwsr-xr-x root /usr/bin/newgrpКаждый setuid-root бинарник — потенциальный вектор повышения привилегий. Если /usr/bin/customtool имеет уязвимость к инъекции команд или path traversal, атакующий может использовать его для запуска root-оболочки. Поэтому аудиты безопасности считают setuid-бинарники, а пентестеры целятся именно в них — один эксплуатируемый setuid-бинарник обходит все остальные контроли доступа.
Бит setgid на каталоге принудительно наследует группу. В обычном каталоге новые файлы получают первичный GID создателя. С setgid на каталоге новые файлы наследуют группу самого каталога — именно этот механизм делает общие каталоги проектов рабочими.
# Общий каталог без setgid — хаос с группами
mkdir /var/project
chown root:devteam /var/project
chmod 775 /var/project
# alice (первичная группа: alice) создаёт файл:
touch /var/project/notes.txt
ls -l /var/project/notes.txt
# -rw-rw-r-- 1 alice alice 0 ... <- группа 'alice', не 'devteam'
# bob не может писать, хотя состоит в devteam
# Исправление: добавить setgid на каталог
chmod g+s /var/project
# или в восьмеричном: chmod 2775 /var/project
ls -ld /var/project
# drwxrwsr-x 2 root devteam 4096 ... <- 's' на месте group-execute
# Теперь alice создаёт файл:
touch /var/project/report.txt
ls -l /var/project/report.txt
# -rw-rw-r-- 1 alice devteam 0 ... <- группа 'devteam' унаследована!
# Setgid на исполняемом бинарнике имеет другой смысл:
# процесс выполняется с GID файла как effective GID (аналогично setuid)
# Пример: /usr/bin/wall имеет setgid 'tty', чтобы писать в терминалы
ls -l /usr/bin/wall
# -rwxr-sr-x 1 root tty 35048 ...Каталоги с setgid — правильное решение для общих рабочих каталогов. Без него получается смесь владений разными группами и половина команды не может редактировать файлы друг друга.
Sticky-бит на каталоге не позволяет пользователям удалять чужие файлы. Без него любой пользователь с правом записи в каталог может удалить любой файл в нём — даже тот, которым он не владеет.
# /tmp — канонический пример: доступен всем для записи, но sticky
ls -ld /tmp
# drwxrwxrwt 20 root root 4096 ...
# ^-- 't' на месте other-execute = sticky + world-executable
# 'T' = sticky без права выполнения для остальных (редко)
# Без sticky: alice может удалить файл bob, если у неё есть право записи в каталог
# С sticky:
# - можно удалять свои файлы
# - можно удалять файлы, которыми ВЛАДЕЕШЬ, независимо от других в каталоге
# - root может удалить всё
# - НЕЛЬЗЯ удалять файлы, принадлежащие другим
# Установить sticky-бит
chmod +t /var/shared
# восьмеричное: chmod 1777 /var/shared (1 = sticky, 777 = rwxrwxrwx)
stat -c '%a %n' /var/shared
# 1777 /var/shared
# Реальная угроза: world-writable каталог БЕЗ sticky-бита
# Любой с правом записи может unlink() любой файл в каталоге
# Классическая атака: rm /var/run/app.pid ; ln -s /etc/cron.d/evil /var/run/app.pid
# Затем дождаться, когда приложение запишет свой PID — оно перезапишет /etc/cron.d/evilАтака через симлинк — классика. World-writable каталог без sticky позволяет любому пользователю удалить файл, заменить его симлинком и ждать, пока привилегированный процесс запишет через него. Поэтому find / -type d -perm -0002 ! -perm -1000 (world-writable каталоги без sticky) — стандартная проверка аудита безопасности.
umask определяет биты прав, которые убираются из вновь создаваемых файлов и каталогов. Это маска битов для снятия, применяемая в момент создания.
# Посмотреть текущий umask
umask
# 0022
# Как вычисляются права новых файлов:
# Файлы начинаются с 0666 (rw-rw-rw-) — execute никогда не устанавливается по умолчанию
# Каталоги начинаются с 0777 (rwxrwxrwx)
# Эффективные = начальные & ~umask
# umask 022:
# ~022 = 755 (binary: 111101101)
# новый файл: 666 & ~022 = 666 & 755 = 644 (rw-r--r--)
# новый каталог: 777 & ~022 = 777 & 755 = 755 (rwxr-xr-x)
touch test_file && ls -l test_file
# -rw-r--r-- 1 alice alice 0 ... <- 644, подтверждено
# Более строгий umask для общих сред:
umask 027 # убирает group write + все права остальных
# новый файл: 666 & ~027 = 666 & 750 = 640 (rw-r-----)
# новый каталог: 777 & ~027 = 777 & 750 = 750 (rwxr-x---)
# Установить umask в профиле оболочки для постоянства
echo 'umask 027' >> ~/.bashrc
# Системный умолчальный в /etc/login.defs (строка UMASK)
grep '^UMASK' /etc/login.defs
# UMASK 022umask 022 означает «не давать группе и остальным право записи». umask 027 добавляет «и остальным не давать право чтения или выполнения». Сервисы, записывающие лог-файлы или временные файлы, наследуют umask демона — демон с umask 000 создаёт world-writable файлы, что является распространённой ошибкой в init-скриптах, не устанавливающих umask явно до сброса привилегий.
POSIX ACL позволяют давать права конкретным пользователям и группам за пределами модели из девяти битов. Когда нужно «alice, bob и группа ci-runner могут читать этот файл, но больше никто» — ACL дают такой ответ, который стандартная модель owner/group/other выразить не может.
# Установить инструменты ACL (обычно уже установлены)
apt install acl # Debian/Ubuntu
# Дать alice права rw на файл, которым она не владеет
setfacl -m u:alice:rw /etc/app/config.conf
setfacl -m g:ci-runners:r /etc/app/config.conf
# Прочитать ACL
getfacl /etc/app/config.conf
# # file: etc/app/config.conf
# # owner: root
# # group: root
# user::rw- <- права владельца (root)
# user:alice:rw- <- alice получает rw
# group::r-- <- owning group (root) получает r
# group:ci-runners:r-- <- группа ci-runners получает r
# mask::rw- <- потолок эффективных прав для именованных записей
# other::--- <- остальные ничего не получают
# Маска: именованные ACL-записи ANDируются с маской при применении
setfacl -m m::r /etc/app/config.conf # теперь alice:rw & mask:r → эффективно r
# Удалить конкретную ACL-запись
setfacl -x u:alice /etc/app/config.conf
# Удалить все ACL (вернуть стандартные права)
setfacl -b /etc/app/config.conf
# ACL на каталогах: -d устанавливает умолчальные ACL, наследуемые новыми файлами
setfacl -d -m u:alice:rw /var/project/
# Новые файлы в /var/project/ унаследуют alice:rwСимвол + в конце вывода ls -l сигнализирует о наличии ACL (-rw-r--r--+). Маска — функция ACL, которая чаще всего удивляет операторов: если ты выполнишь chmod g+w file на файле с ACL, ты изменишь маску, что незаметно ограничит эффективные права всех именованных записей.
Настройка общего каталога сборки, куда пишут и разработчики, и CI, но файлы всегда принадлежат группе проекта.
Цель: /var/builds/myapp/ — разработчики (группа dev) и CI-runner (пользователь ci-runner) оба могут писать. Файлы должны всегда принадлежать группе dev. Никто вне dev или ci-runner не должен ничего читать.
# Шаг 1: создать каталог с setgid и строгими правами
sudo mkdir -p /var/builds/myapp
sudo chown root:dev /var/builds/myapp
sudo chmod 2770 /var/builds/myapp
# 2 = setgid, 7 = rwx (владелец/root), 7 = rwx (группа/dev), 0 = --- (остальные)
ls -ld /var/builds/myapp
# drwxrws--- 2 root dev 4096 ...
# Шаг 2: дать ci-runner права через ACL (он не в группе dev)
sudo setfacl -m u:ci-runner:rwx /var/builds/myapp
sudo setfacl -d -m u:ci-runner:rwx /var/builds/myapp # наследовать новым файлам
# Шаг 3: проверить
getfacl /var/builds/myapp
# user::rwx
# user:ci-runner:rwx
# group::rwx
# mask::rwx
# other::---
# default:user::rwx
# default:user:ci-runner:rwx
# default:group::rwx
# default:mask::rwx
# default:other::---
# Шаг 4: тест — ci-runner создаёт файл
sudo -u ci-runner touch /var/builds/myapp/artifact.tar.gz
ls -l /var/builds/myapp/artifact.tar.gz
# -rw-rw----+ 1 ci-runner dev 0 ... <- группа 'dev' через setgid; + означает ACLКомбинация setgid (наследование группы) и умолчального ACL (права конкретного пользователя, распространяющиеся на дочерние файлы) — идиоматическое решение для таких сценариев с несколькими владельцами.
▸Частая ошибка
Распространённая ошибка при установке ACL — забыть о маске. Если ты выполнишь setfacl -m u:alice:rw file, а затем chmod 644 file, ты только что установил маску в r-- (chmod на файле с ACL изменяет маску через биты группы). Запись rw для alice теперь имеет эффективное право r, потому что ANDируется с маской. Всегда перепроверяй getfacl после любого chmod на файле с ACL, чтобы убедиться, что эффективные права соответствуют ожиданиям.
▸Почему это работает
Почему sticky-бит имеет такое странное название? В оригинальном Unix на PDP-11 (начало 1970-х) sticky-бит означал «держать текстовый сегмент этой программы в свопе, даже когда она не запущена» — подсказка производительности для часто используемых бинарников. Современные ядра полностью игнорируют его на файлах (VM-подсистема справляется сама). Бит был переосмыслен для каталогов в BSD Unix: «только удаляй свои файлы». Linux унаследовал семантику для каталогов, но отказался от семантики для файлов. Поэтому man chmod до сих пор документирует оба значения — одно историческое, второе реально используемое.
Ты выполняешь 'umask 027', затем 'mkdir newdir'. Какие права получит newdir, и какими будут права нового файла, созданного командой 'touch newfile'?
За пределами rwx существуют три специальных бита. Setuid (4000) заставляет бинарник выполняться от имени его владельца — механизм /usr/bin/passwd и вектор повышения привилегий при злоупотреблении. Setgid (2000) на каталоге принудительно наследует группу для новых файлов — решение для общих рабочих каталогов. Sticky (1000) на world-writable каталоге не позволяет пользователям удалять чужие файлы — именно так работает /tmp. umask — это маска, применяемая при создании: файлы начинаются с 0666, каталоги с 0777, минус биты umask. POSIX ACL (setfacl/getfacl) добавляют права конкретным пользователям и группам за пределами модели из девяти битов; маска ACL ограничивает эффективные права именованных записей. Запусти chmod на файле с ACL — изменишь маску, а не только права группы.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.