Короткий ответ
SUID root (chmod u+s) на непакетированном бинаре — локальный root. Снимите инвентарь find / -xdev -perm -4000, сравните с dpkg -S / известным списком Ubuntu, снимите bit с /usr/local, /opt, /home, /tmp. Не трогайте без понимания sudo, su, passwd, newgrp. World-writable SUID — снять bit немедленно. Не заменяйте SUID на chmod 777. Хост host.example (10.0.20.10).
Симптомы и как отличить
- В
/usr/local/bin/cleanupстоитrwsr-xr-x root; - бинарь не принадлежит ни одному пакету;
- SGID на каталогах ожидают (games) vs SGID на скрипте python.
| Bit | Смысл |
|---|---|
| 4000 SUID | euid владельца файла |
| 2000 SGID | egid; на каталоге — наследование группы |
| 1000 sticky | /tmp |
Отличие от capabilities getcap: современный ping часто cap, не suid. Отличие от сервиса root: долгоживущий uid 0 vs exec SUID. unit.
Возможные причины
- Самописный «чтобы пользователи монтировали».
- Старый
chmod +sпосле Permission denied. - Копия с другого дистрибутива.
- Малварь в /tmp.
- NFS no_root_squash.
- Контейнер volume с suid (часто nosuid на mounts — проверьте опции).
Диагностика
sudo find / -xdev -perm -4000 -type f -printf '%m %u %g %p\n' 2>/dev/null | sort
sudo find / -xdev -perm -2000 -type f -printf '%m %u %g %p\n' 2>/dev/null | sort-xdev не уйдёт на bind-mount данные; пройдите отдельные тома явно (/var, /opt).
Пакет:
dpkg -S /usr/bin/passwd
dpkg -S /usr/local/bin/cleanup 2>&1Writable + SUID:
sudo find / -xdev -perm -4000 -perm -0002 -type f 2>/dev/null
sudo find / -xdev -perm -4000 -writable -type f 2>/dev/nullMount nosuid:
findmnt -o TARGET,OPTIONS | grep -E 'nosuid|suid'/tmp с suid — плохо.
getcap -r /usr/bin /usr/sbin 2>/dev/null | headРешение
Сценарий A. Чужой бинарь в /usr/local или /opt
sudo chmod u-s /usr/local/bin/cleanup
stat /usr/local/bin/cleanupНужные привилегии — systemd unit с User= и capabilities, sudoers Cmnd_Alias, не SUID. Если это бэкап — cron без writable.
Сценарий B. World-writable SUID
Сразу chmod u-s и уберите write for other: права. Считайте инцидент: кто положил, когда.
Сценарий C. Пакетный SUID, которого нет в золотом образе
Сверьте с чистой Ubuntu той же версии. Лишний пакет — apt-get remove. Не chmod u-s на passwd.
Типично легитимны (не исчерпывающий вечный список — сверяйте со своей системой): passwd, su, sudo, newgrp, chfn, chsh, mount/umount (на части релизов уже cap), pkexec. Если сомневаетесь — сравните с эталонной VM, не с форумом 2014 года.
Сценарий D. Нужен privileged bind без SUID
setcap cap_net_bind_service=+ep на конкретный бинарь плюс AppArmor, или proxy. Capabilities тоже риск, но уже не полный uid 0.
mount -o nosuid на /home, /tmp, /opt если политика позволяет (ломает редкий легитимный SUID там — обычно и не нужен).
Как сравнить с эталоном без гадания. Поднимите чистую VM той же lsb_release и find /usr /bin /sbin -perm -4000, сохраните список. Diff с продом покажет лишнее в /usr/local и пакеты, которых нет в золотом образе. Не скачивайте «список SUID Ubuntu» со случайного сайта — релизы отличаются (mount suid vs cap).
dpkg -V на пакет с известным suid покажет изменённый mode. Если passwd без SUID — кто-то уже «ужесточил» и сломает passwd пользователям. Верните пакет: apt-get install --reinstall passwd, не выдумывайте chmod 4755 по памяти без stat с эталона.
Bind-mount /tmp с suid,exec: исправьте fstab на nosuid,nodev,noexec если политика позволяет (ломает редкие легитимные инсталляторы в /tmp — обычно и не нужны на сервере). Проверка findmnt /tmp.
Контейнер runtime часто монтирует с nosuid. Исключение: привилегированный контейнер и bind хостового /. Тогда SUID на хосте снова важен.
После снятия bit проверьте функционал: если это был «удобный ping для user» — пакетный iputils-ping с cap. Если «удобный backup» — sudoers Cmnd_Alias или unit. Пользователи не должны требовать SUID на самописке.
Документ baseline: хэш списка find … -perm -4000 в заявке. Еженедельный diff в мониторинг.
find с -perm -4000 не показывает capabilities. После зачистки SUID прогоните getcap -r /usr/local /opt 2>/dev/null. Неожиданный cap_sys_admin+ep на самописке — тот же класс риска. Снимайте setcap -r файл осознанно.
Не храните эталонный список SUID только в голове. Файл baseline-suid.txt в ansible рядом с плейбуком, diff в CI против find с прода (через ssh admin). Расхождение без тикета — стоп выкладки.
Список эталона обновляйте после смены релиза (22.04→24.04): пакетный набор SUID меняется, diff к старому эталону будет ложноположительным.
Как проверить, что проблема устранена
sudo find /opt /usr/local /home /tmp /var/tmp -xdev -perm -4000 -type f
stat /usr/bin/sudo | grep Uid
findmnt /tmpНет SUID в home/opt/tmp. sudo работает у admin. Система грузится, passwd не сломан. Список пакетных SUID сохранён в заявке как baseline.
Если не помогло
- Bit вернулся после apt: это пакет, не «малварь» автоматически — смотрите changelog.
- Bit вернулся из ansible
mode: '4755'. - Overlay/rootfs immutable.
- Контейнер без nosuid на bind.
- AppArmor не замена снятию SUID, но DENIED может маскировать тест.
Профилактика
- Еженедельный diff списка SUID vs эталон.
- Запрет mode 4xxx в деплое своих бинарей.
- nosuid на user-writable томах.
- Аудит пользователей после находки в /home.
FAQ
Снимать SUID с ping?
На новых Ubuntu ping часто с cap, не suid. Смотрите getcap/stat. Не копируйте старые гайды.
SGID на /var/mail
Ожидаемо для почты. Не трогайте пакетное, если не знаете.
find без -xdev
Уйдёт в /proc и сетевые ФС, шум и риск. Используйте -xdev + явные тома.
Можно ли SUID на скрипт bash?
Не работает как хотят, опасно как обман. Не делайте.
pkexec и polkit
Отдельная политика. Не disable polkit вместо инвентаризации SUID.