# SUID, SGID, sticky bit - спецбиты прав _Файловая система · LinuxLab Knowledge Base_ **TL;DR:** Три спецбита поверх обычных rwx: **SUID** - запуск с правами владельца файла, **SGID** - с правами группы (или наследование группы на каталоге), **sticky** - удалить может только владелец файла (важно для `/tmp`). ## Зачем нужны спецбиты Обычная схема `rwxr-xr-x` отвечает на вопрос «кто что может». Но иногда нужно дать не-root юзеру **временно** делать привилегированную операцию: поменять свой пароль (запись в `/etc/shadow`, доступен только root), открыть raw-сокет для `ping`, монтировать через `mount`. Для этого Linux вводит три спецбита поверх rwx. ## Где они в `ls -l` Спецбиты заменяют x в выводе `ls -l`: ``` -rwsr-xr-x root root /usr/bin/passwd # SUID (s в позиции owner-x) -rwxr-sr-x root tty /usr/bin/wall # SGID (s в позиции group-x) drwxrwxrwt root root /tmp # sticky (t в позиции other-x) ``` Если бит стоит, а x не было - заглавная буква (`S`/`T`): «бит выставлен, но execute не работает». Часто опечатка в `chmod`. Числовое представление в `chmod`: ставится **четвёртой** цифрой слева: | Бит | Значение | Пример | |--------|----------|--------------| | SUID | 4 | `chmod 4755` | | SGID | 2 | `chmod 2755` | | sticky | 1 | `chmod 1777` | Можно складывать: `chmod 6755` = SUID+SGID. Текстовая форма: `chmod u+s`, `g+s`, `+t`. ## SUID - запуск с правами владельца При запуске бинаря с SUID-битом **effective UID** процесса становится UID владельца файла (не запускающего). Если файл принадлежит root - процесс получает root-права на время своего выполнения. ```bash ls -l /usr/bin/passwd # -rwsr-xr-x 1 root root ... /usr/bin/passwd ``` Юзер `serge` запускает passwd → effective UID становится 0 (root) → запись в `/etc/shadow` (доступна только root) разрешена → пароль меняется. Без SUID невозможно было бы сделать `passwd`, `sudo`, `mount`, `su`. **Критически важные нюансы Linux:** 1. **На скриптах SUID игнорируется**. Ядро Linux намеренно игнорирует SUID на shebang-скриптах из-за TOCTOU race condition (между чтением shebang и exec интерпретатора файл может быть подменён). Только ELF-бинари. Если нужен «root-скрипт» - обернуть в C/Go-бинарь либо [sudo](/kb/sudo.md). 2. **SUID не работает на ФС смонтированных с `nosuid`**. Стандартная практика безопасности - `mount -o nosuid /home`, `/tmp`. Проверить: `findmnt | grep nosuid`. 3. **SUID - security smell в современных системах**. Современная замена - [capabilities](/kb/capabilities.md): дать процессу только конкретную капабилу (CAP_NET_RAW для ping вместо полного root). На современных дистрибутивах `/usr/bin/ping` уже не SUID, а имеет `cap_net_raw=ep`. ## SGID - два разных режима ### На бинаре - то же что SUID, но для группы Effective GID = группа файла. Используется для бинарей которые читают файл, доступный только определённой группе: ```bash ls -l /usr/bin/wall # -rwxr-sr-x root tty ... # → wall пишет в tty всех юзеров (группа tty), не имея root ``` ### На каталоге - наследование группы (gid inheritance) ЭТО ВАЖНЕЕ. Новые файлы создаваемые в каталоге получают **группу каталога**, а не primary group создателя. Используется для shared-папок: ```bash sudo mkdir /srv/team sudo chown root:devs /srv/team sudo chmod 2775 /srv/team # SGID + rwxrwxr-x # Теперь: cd /srv/team touch foo.txt ls -l foo.txt # -rw-rw-r-- 1 serge devs ... foo.txt ← группа devs, не serge ``` Без SGID файлы получили бы primary group юзера (часто `serge:serge`), и другие члены команды не смогли бы их редактировать. ## Sticky bit - защита от удаления чужого На каталоге с правами `rwx` любой юзер может удалить **любой** файл внутри (потому что удаление = модификация каталога, а не файла). Для shared-папок типа `/tmp` это проблема - Алиса может стереть файл Боба. Sticky bit меняет правило: **удалить файл из каталога может только владелец файла** (или root). ```bash ls -ld /tmp # drwxrwxrwt 22 root root ... /tmp ← `t` в конце = sticky # Создать sticky-каталог: sudo mkdir /shared sudo chmod 1777 /shared ``` На обычных файлах sticky не имеет смысла на современных Linux (исторически означал «держать в swap», давно неактуально). ## Аудит - найти все SUID/SGID на хосте ```bash # все SUID-файлы sudo find / -xdev -perm -4000 -type f 2>/dev/null # все SGID-файлы sudo find / -xdev -perm -2000 -type f 2>/dev/null # SUID или SGID sudo find / -xdev \( -perm -4000 -o -perm -2000 \) -type f 2>/dev/null ``` Флаг `-xdev` - не уходить за пределы текущей ФС (важно: иначе перейдёт в `/proc`, `/sys`, NFS-монтировки). Любой новый SUID-файл на проде = повод разобраться. Эталонный набор обычно: `passwd`, `sudo`, `mount`, `umount`, `su`, `chsh`, `chfn`, `newgrp`, `pkexec`, `chage`. Дистро-специфичные могут быть, но всё что не оттуда - подозрительно. ## Удалить SUID/SGID/sticky ```bash chmod u-s /path/to/file # снять SUID chmod g-s /path/to/file # снять SGID chmod -t /path/to/dir # снять sticky ``` Или числом: `chmod 0755` явно сбрасывает спецбиты в 0. ## Команды ```bash ls -l /usr/bin/passwd /usr/bin/sudo ``` Увидеть SUID-бит (буква s) у классических бинарей которые требуют root ```bash sudo find / -xdev -perm -4000 -type f 2>/dev/null ``` Все SUID-бинари на корневой ФС - стандартный security-аудит ```bash sudo chmod 2775 /srv/shared && sudo chown :team /srv/shared ``` Shared-папка с SGID: новые файлы автоматически получают группу team ```bash sudo chmod 1777 /scratch ``` Sticky-каталог как /tmp: каждый пишет, удалять можно только своё ```bash getcap /usr/bin/ping ``` Проверить capabilities - современная замена SUID для системных бинарей ## См. также - [File permissions: rwx и chmod](/kb/file-permissions.md) - [POSIX ACL - расширенные права доступа](/kb/posix-acl.md) - [Linux capabilities - биты привилегий](/kb/capabilities.md) - [sudo - выполнить от имени root](/kb/sudo.md) - [Extended attributes (xattr) - произвольные метаданные файла](/kb/extended-attributes.md)