Найти лишние учётки с нулевым UID
getent passwd | awk -F: '($3 == 0) {print $1}'
Нюанс: в подборках пишут
awk -F: '($3 == "0")' — со строковым сравнением. Оно пропускает UID, записанный как 00 или 0000. Проверил: завёл пользователя с -u 00, id показал uid=0(root), то есть для ядра это полноценный рут, а строковая проверка его не увидела. Без кавычек awk сравнивает числа и ловит все варианты.getent вместо cat /etc/passwd нужен, чтобы захватить пользователей из LDAP и SSSD.Убедиться, что root не пускают по SSH
sshd -T | grep -i permitrootlogin
Нюанс, и он главный.
grep по /etc/ssh/sshd_config показывает то, что написано, а не то, что действует. Собрал стенд: в основном конфиге PermitRootLogin no, а в /etc/ssh/sshd_config.d/99-cloud.conf — yes. Строка Include стоит выше, drop-in побеждает:
grep -> PermitRootLogin no
sshd -T -> permitrootlogin yes
Именно так выглядит типовой облачный образ.
sshd -T печатает итоговую конфигурацию после всех включений.Проверить sudoers перед сохранением
visudo -c -f /etc/sudoers.d/devops
visudo без аргументов знают все, а вот -c -f работает с любым файлом и годится для CI или проверки после Ansible. На кривом правиле показывает строку и место ошибки, на нормальном — parsed OK. Заодно sudo -l покажет, что реально разрешено текущему пользователю.Найти SUID-бинарники
find / -xdev -perm /6000 -type f -ls 2>/dev/null
Нюанс:
-perm -4000 -user root из чек-листов пропускает SGID. На моей машине разница 9 файлов против 12 — мимо проверки прошли chage, expiry, ssh-agent. Фильтр -user root тоже лишний: чужой SUID опаснее рутового, а он под этот фильтр не попадёт. И -xdev обязателен, иначе find захлебнётся на /proc.Про
sudo -i вместо su спорить не буду, но помнить стоит другое: жёсткие правила в sudoers обходятся через less, find, awk и десяток других утилит — у всех есть побег в шелл. Разрешать по одной команде безопаснее, чем кажется, только если это не интерпретатор.А вы root на серверах отключаете совсем или держите для аварийной консоли?
#Linux #Security #SSH #sudo #DevOps