MAATRIX / Блог / Ревизия пользователей системы: кто такой backup2 и почему у него sudo

Ревизия пользователей системы: кто такой backup2 и почему у него sudo

MAATRIX

Открываете /etc/passwd на сервере, который держите год или два, и натыкаетесь на строку backup2:x:1003:1003::/home/backup2:/bin/bash. Кто это заводил, зачем, почему у него есть домашняя директория и — что хуже — почему он состоит в группе sudo, никто уже не помнит. Такая ситуация типична: учётные записи создаются для разовой задачи или теста и остаются на сервере навсегда, потому что удалять непонятное страшнее, чем оставить как есть. Ниже — рабочий подход к ревизии: как получить полный список пользователей, разобраться с назначением каждого, и проверить, кому и почему разрешено становиться root через sudo.

Почему пользователи со временем становятся угрозой

Учётные записи на сервере накапливаются незаметно, и у этого почти всегда одна и та же механика. Кто-то заводит пользователя deploy-test, чтобы один раз прогнать скрипт из CI без риска сломать основной аккаунт — и забывает удалить его после теста. Подрядчик просит временный доступ на неделю разобраться с багом, получает sudo без ограничения по времени, и через полгода про него никто не вспоминает. Скрипт при установке создаёт сервисного пользователя backup2 (потому что backup уже был занят), кто-то на скорую руку добавляет его в sudo, чтобы решить одну ошибку с правами доступа — и забывает откатить.

Проблема не в том, что такие аккаунты существуют — иногда они действительно нужны. Проблема в том, что причина их существования не документируется нигде, кроме памяти человека, который это делал, а он увольняется, переключается на другой проект или просто забывает. Через два-три года на типичном сервере компании из 5-10 человек скапливается 10-20 лишних записей: тестовые, временные, дублирующие, от уволенных сотрудников. Часть из них ничего не может, потому что shell выставлен на /usr/sbin/nologin. Но часть — как backup2 в примере ниже — имеет полноценный shell, ключ в authorized_keys и sudo без пароля. Это уже не техдолг, а реальная поверхность атаки: если скомпрометирован хотя бы один такой ключ, у атакующего сразу есть root.

Отдельно стоит вопрос об уволенных сотрудниках — если у вас есть подозрение, что доступ остался у человека, который уже не работает в компании, это отдельная и более срочная задача: что делать, если сотрудник уволился, а доступ остался.

Инвентаризация: получаем полный список пользователей

Первый шаг ревизии — не гадать по памяти, а вывести полный, объективный список всех учётных записей на сервере. Основной источник — /etc/passwd, но читать его напрямую не всегда правильно, особенно если в системе используется LDAP, SSSD или другой источник учётных записей. Правильнее спрашивать через getent, который учитывает все настроенные источники (NSS):

getent passwd

Это даст длинный список, включающий системных пользователей вроде daemon, www-data, postgres — их трогать не нужно. Интересуют записи с UID выше системного порога — в Debian/Ubuntu и RHEL/CentOS/AlmaLinux это обычно 1000 (иногда 500 в старых версиях). Отфильтровать их можно так:

awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $3, $6, $7}' /etc/passwd

Колонки: имя, UID, домашняя директория, login shell. /bin/bash или /bin/sh означает, что можно интерактивно работать; /usr/sbin/nologin или /bin/false — что вход запрещён на уровне shell (хотя выполнение через sudo -u или cron всё равно возможно). Полезно сразу свести список в таблицу и отметить статус:

ПользовательUIDShellДомашняя директорияПохоже на
ivan1000/bin/bash/home/ivanреальный сотрудник
deploy1001/usr/sbin/nologin/home/deployсервисный, для CI
backup21003/bin/bash/home/backup2непонятно
contractor1004/bin/bash/home/contractorнепонятно, старый

Дальше проверьте, кто из них состоит в привилегированных группах:

getent group sudo
getent group wheel
getent group docker

Группа docker часто недооценивается: членство в ней фактически равносильно root на хосте, потому что через него можно смонтировать корневую файловую систему в контейнер.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Как расследовать назначение каждого пользователя

Главное правило ревизии: не удалять вслепую. Непонятная учётная запись — не повод сразу выполнять userdel, а повод провести небольшое расследование. Удалить всегда успеете, а восстановить забытый, но нужный сервисный аккаунт бывает больно — особенно если под него настроен cron-джоб, который вы не сразу свяжете с исчезнувшим пользователем. Для каждого подозрительного имени пройдите такой чек-лист.

Когда и с какого IP заходили под этой учётной записью. Даёт первое представление, живой аккаунт или мёртвый:

lastlog -u backup2
last -a | grep backup2

«Never logged in» — частый признак сервисного аккаунта, под который никогда не входили интерактивно, а использовали только для выполнения скриптов от его имени.

Есть ли у пользователя crontab. Регулярные задачи по расписанию — частая причина, почему сервисный пользователь вообще существует:

crontab -l -u backup2
ls -la /var/spool/cron/crontabs/  # Debian/Ubuntu
ls -la /var/spool/cron/           # RHEL/CentOS/AlmaLinux

Владеет ли пользователь файлами или процессами в системе. Поиск по всей файловой системе может занять время на медленном диске, но даёт исчерпывающий ответ:

find / -xdev -user backup2 2>/dev/null
ps -u backup2

Если находится каталог со свежими файлами — например, /var/backups/db со вчерашними дампами — вопрос «зачем он нужен» закрыт: это рабочий сервисный аккаунт, а не мусор.

Есть ли SSH-ключи и когда они добавлены. Ключ без пароля даёт прямой удалённый доступ, и его происхождение важно понять отдельно:

cat /home/backup2/.ssh/authorized_keys
stat /home/backup2/.ssh/authorized_keys

stat покажет время изменения файла — не создание аккаунта, но подсказку, когда ключ последний раз трогали. Ключ с комментарием вроде contractor@laptop двухлетней давности от подрядчика, который давно не работает с проектом, — прямой кандидат на отключение независимо от прав sudo. Похожий разбор случая с забытым ключом есть в статье про аудит ключа подрядчика в authorized_keys.

Есть ли следы в журналах авторизации. Помогает понять, использовался ли аккаунт для входа по паролю или только по ключу, и не появлялся ли он в контексте ошибок аутентификации:

grep backup2 /var/log/auth.log*      # Debian/Ubuntu
grep backup2 /var/log/secure*        # RHEL/CentOS/AlmaLinux
journalctl -u sshd | grep backup2

Если настроен auditd, проверьте и его — он покажет более полную картину запуска процессов от имени пользователя: ausearch -ua backup2 2>/dev/null.

Только после того как собраны эти пять пунктов, есть смысл принимать решение: оставить, ограничить или деактивировать.

История backup2: разбор конкретного случая

Возьмём пример, максимально приближенный к типичной находке на сервере, который никто системно не ревизировал год-полтора. Учётная запись backup2 с UID 1003, shell /bin/bash, входит в группу sudo. Проходим чек-лист по порядку:

  • lastlog -u backup2 → «Never logged in» — под этим именем никто не входил интерактивно ни разу, аккаунт использовался программно, а не человеком;
  • crontab -l -u backup2 → пустой список, регулярных заданий нет, несмотря на говорящее имя;
  • find / -xdev -user backup2 2>/dev/null → только домашняя директория с дефолтными файлами из /etc/skel и пустым .bash_history, ни одного реального файла с данными бэкапов;
  • cat /home/backup2/.ssh/authorized_keys → один ключ с комментарием # temp access for db migration, stat на файл показывает время изменения четырнадцать месяцев назад;
  • sudo -l -U backup2 → пользователь входит в группу sudo, а правило в /etc/sudoers для группы — %sudo ALL=(ALL:ALL) ALL с отдельной строкой NOPASSWD, добавленной при том же инциденте.

Картина складывается: полтора года назад кто-то делал разовую миграцию базы данных, завёл backup2 (имя неудачное — наводит на мысль о постоянном сервисе бэкапов, хотя это был разовый доступ), дал sudo без пароля, чтобы не разбираться с правами на файлы БД, и забыл всё убрать. Аккаунт мёртв: ни входов, ни задач, ни файлов — только ключ и root-доступ, которым в теории может воспользоваться кто угодно с этим приватным ключом.

Правильно не удалять такую находку сразу, а заблокировать (шаги ниже), выдержать период наблюдения и только потом убрать полностью. Здесь, поскольку все пять проверок независимо указывают на «мёртвый и опасный» аккаунт, период наблюдения можно сократить до недели-двух, а не растягивать на месяцы.

Ревизия sudo: кто и что может от имени root

Список пользователей — только половина работы: даже без лишних учётных записей sudo часто настроен избыточно широко для тех, кто реально нужен. Начните с базовой конфигурации:

sudo cat /etc/sudoers

Стандартная строка в Ubuntu/Debian выглядит так:

%sudo   ALL=(ALL:ALL) ALL

В RHEL/CentOS/AlmaLinux — аналогично, но через группу wheel:

%wheel  ALL=(ALL:ALL) ALL

Это означает: любой член группы, любую команду, с запросом пароля (явного NOPASSWD тут нет). Само по себе это нормальная дефолтная настройка. Проблема начинается там, где кто-то добавляет более широкое правило поверх — обычно в отдельных файлах:

sudo ls -la /etc/sudoers.d/
sudo cat /etc/sudoers.d/*

Именно здесь чаще всего находятся временные и забытые правила — их удобно добавлять точечно, но так же удобно забыть навсегда. Ищите три паттерна риска:

NOPASSWD на широкую команду. backup2 ALL=(ALL) NOPASSWD: ALL — это root без пароля для кого угодно, кто получит доступ к учётной записи. Если NOPASSWD действительно нужен (например, для CI/CD), он должен быть максимально сужен до конкретной команды:

deploy ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart myapp

Правило для несуществующего или неактивного пользователя. Если в sudoers упомянут пользователь, которого уже нет в /etc/passwd, правило — мёртвый груз, но если аккаунт когда-нибудь создадут заново с тем же именем, он неожиданно получит sudo. Сверяйте оба списка.

Дублирующиеся или противоречащие друг другу правила. Sudo применяет последнее совпавшее правило, поэтому несколько файлов, редактировавшихся в разное время разными людьми, могут давать не тот результат, который ожидается при беглом чтении одного файла. Проверить итоговые эффективные права для конкретного пользователя надёжнее, чем читать конфиг построчно:

sudo -l -U ivan
sudo -l -U backup2

Команда показывает сумму всех применимых правил, а не отдельные файлы. Регулярно прогоняйте её по всем пользователям с shell, отличным от nologin.

Редактировать /etc/sudoers и файлы в /etc/sudoers.d/ нужно только через visudo — он проверяет синтаксис перед сохранением и не даёт оставить сервер с битым конфигом:

sudo visudo
sudo visudo -f /etc/sudoers.d/deploy

Если правки уже внесены напрямую (не через visudo) и есть подозрение на ошибку синтаксиса, проверить можно так, не трогая файл:

sudo visudo -c

Регламент: как сделать ревизию регулярной, а не разовой

Разовая чистка снимает текущий техдолг, но без регламента он накопится снова за полгода-год. Практический минимум, который реально соблюдается:

Снимок состояния при каждой ревизии. Сохраняйте вывод инвентаризации в файл с датой — так следующая ревизия сразу покажет, что появилось нового:

getent passwd | awk -F: '$3>=1000 && $3<65534 {print $1, $3, $6, $7}' > /root/user-audit-$(date +%F).txt

Сравнение с предыдущим снимком через diff за секунды покажет все новые и удалённые учётные записи с прошлого раза.

Реестр назначения каждого пользователя. Простой текстовый файл или запись в вики с полями: имя, зачем создан, кем, дата, срок действия (если временный). Без него расследование каждый раз начинается с нуля, как с backup2 выше.

Срок действия для временных доступов. Если аккаунт заводится для подрядчика или разовой задачи, сразу выставляйте дату истечения через chage, а не полагайтесь на то, что кто-то вспомнит убрать доступ вручную:

sudo chage -E 2026-09-30 contractor
sudo chage -l contractor

По истечении даты аккаунт блокируется системой автоматически, без ручного вмешательства в нужный день.

Периодичность. Раз в квартал — разумный баланс для небольшой команды; для более крупной инфраструктуры или после смены состава сотрудников имеет смысл делать это чаще. Общий подход к плановому аудиту сервера, куда ревизия пользователей входит одним из пунктов, — в статье аудит сервера своими силами: план на выходные.

Порядок деактивации, а не мгновенное удаление. Когда находка похожа на историю backup2 из примера выше, правильная последовательность — заблокировать, понаблюдать, потом удалить, а не выполнять userdel сразу же после обнаружения:

sudo usermod -L backup2                    # заблокировать пароль
sudo usermod -s /usr/sbin/nologin backup2   # запретить интерактивный вход
sudo gpasswd -d backup2 sudo                # убрать из sudo немедленно, это не ждёт

Ключи из authorized_keys для такого аккаунта стоит убрать сразу — блокировка пароля не мешает входу по ключу. После периода наблюдения (одна-две недели для явно мёртвого аккаунта, дольше — если есть сомнения) и при отсутствии активности:

sudo tar czf /root/archive-backup2-$(date +%F).tar.gz /home/backup2
sudo userdel -r backup2

Архив домашней директории перед удалением — дешёвая страховка: если через месяц выяснится, что аккаунт всё-таки был кому-то нужен, восстановить файлы можно за минуту, а не по бэкапам всей системы. Базовые принципы создания и разграничения учётных записей, которые полезно держать в голове при заведении новых пользователей (чтобы через год не разбирать очередной backup3), — в статье про управление пользователями и группами в Linux.

Отдельно проверьте, не остались ли у деактивированных пользователей задачи в cron, которые продолжат выполняться даже при запрете login: пример разбора reverse shell, найденного именно в crontab у пользователя, которого никто сознательно не заводил, — в статье reverse shell в cron у пользователя, которого не заводили.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли просто удалить всех пользователей, которых никто не узнаёт, разом?

Нет. Сначала заблокируйте вход (usermod -L, shell на nologin) и уберите из привилегированных групп, выдержите паузу в одну-две недели, проверьте логи и мониторинг на предмет сломавшихся задач — и только потом удаляйте с архивированием домашней директории.

Как отличить системного пользователя от человека, если имя не говорящее?

Смотрите на UID: системные учётные записи обычно имеют UID ниже 1000, «человеческие» и добавленные вручную сервисные — от 1000 и выше. Плюс shell: /usr/sbin/nologin почти всегда означает сервисный аккаунт без интерактивного входа.

NOPASSWD в sudoers — это всегда плохо?

Нет, для узкой конкретной команды (например, перезапуск одного systemd-юнита из CI) это нормальная практика. Опасен NOPASSWD на ALL — root без пароля на что угодно.

Что делать, если непонятно, кто именно завёл подозрительного пользователя?

Проверьте метки времени в /var/log/auth.log (или /var/log/secure) рядом с датой создания домашней директории (stat /home/имя) и сопоставьте с историей деплоев за тот период. Если журналы уже прошли ротацию, ориентируйтесь на пять признаков активности из раздела про расследование — этого обычно достаточно для решения даже без точного авторства.

Стоит ли автоматизировать ревизию скриптом?

Да: скрипт, который раз в месяц сравнивает getent passwd и sudo -l -U с прошлым снимком и присылает diff, экономит часы ручной проверки. Но решение по каждой находке — оставить, ограничить, удалить — должно оставаться за человеком.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →