Короткий ответ

Аудит пользователей — таблица: имя, UID, shell, lock (passwd -S), lastlog, группы (sudo,docker), sudo -l, ключи SSH, crontab. Сверьтесь с HR и с system users. Действия по находкам — отдельные: мёртвые учётки, sudo ALL, ключи. Не удаляйте UID<1000. Хост host.example (10.0.20.10), живой вход admin.

Симптомы и как отличить

Нет процедуры, если «кто-то в sudo» неизвестно. Это не расследование конкретного взлома (там ещё auditd/journal). Для следов изменений: auditd.

Возможные причины мусора

  1. Cloud-init users.
  2. Уволенные.
  3. Тестовые adduser.
  4. Пакеты с system user ≥1000.
  5. Дубль локальный+домен.

Диагностика (чеклист съёмки)

Сохраняйте файлы.

1. Учётки

mkdir -p /home/admin/user-audit
getent passwd > /home/admin/user-audit/passwd.txt
getent passwd | awk -F: '{printf "%s uid=%s gid=%s shell=%s home=%s\n",$1,$3,$4,$7,$6}'

Интерактивные кандидаты: UID≥1000 и shell не nologin/false.

getent passwd | awk -F: '$3>=1000 && $7 !~ /nologin|false/ {print}'

Второй uid 0:

getent passwd | awk -F: '$3==0 {print}'

Только root.

2. Lock и пароль

sudo passwd -S -a > /home/admin/user-audit/passwd-S.txt

Интерпретация: L locked, P usable password, NP empty. NP у интерактива + SSH ключ — зафиксируйте.

3. lastlog / last

lastlog > /home/admin/user-audit/lastlog.txt
last -a | head -n 40

Never у человека из HR = кандидат на lock. Never у myservice = норма.

4. sudo

sudo visudo -c
sudo grep -REn '^[^#]' /etc/sudoers /etc/sudoers.d/ > /home/admin/user-audit/sudoers.txt
for u in admin deploy ivan; do echo "== $u"; sudo -l -U "$u"; done

Подставьте свои имена из шага 1.

5. Группы высокого риска

getent group sudo docker lxd adm systemd-journal
id admin

6. Ключи и cron

sudo find /home -name authorized_keys -ls
sudo ls /var/spool/cron/crontabs

Fingerprint: ssh-keygen -lf.

7. Процессы «лишних»

ps -eo user,pid,cmd | awk 'NR==1 || $1=="ivan"'

Решение (как оформить результат)

Таблица:

UserUIDShellSlastlogsudodockerkeysРешение
admin1000bashPtoday%sudoнет1оставить
ivan1001bashP400dNOPASSWD ALLда2lock+отзыв
myservice115nologinLneverнетнетнетоставить

Каждая строка «lock/отзыв» — тикет, не сюрприз ночью. Baseline хоста: hardening.

LDAP: повторите для доменных sudoers (sss). Локальный lock не снимает доменную учётку.

Скрипт съёмки, чтобы не забывать поля. Достаточно shell от admin:

{
  echo '=== passwd uid>=1000 ==='
  getent passwd | awk -F: '$3>=1000 {print}'
  echo '=== passwd uid 0 ==='
  getent passwd | awk -F: '$3==0 {print}'
  echo '=== groups sudo docker ==='
  getent group sudo docker
} | sudo tee /home/admin/user-audit/summary.txt

Не парсите /etc/shadow в wiki. passwd -S достаточно.

Сверка с HR: таблица сотрудников vs интерактивные shells. Лишние в Linux — lock. Лишние в HR без учётки — не ваша дыра, но ключ мог жить под admin. Сверяйте fingerprint ключей с инвентарём ноутбуков.

nologin пользователи с tty в last: кто-то сменил shell обратно. Смотрите usermod -s.

Пакет accountsservice и GUI на сервере обычно не нужны; если есть gdm users — зачем графическая сессия на host.example.

w/who в момент аудита: живые сессии уволенных — terminate, затем lock.

Экспорт в тикет без секретов: не кладите содержимое authorized_keys целиком в публичный канал, только comment+fingerprint.

Повторный аудит после любого offboarding через 7 дней: ключ могли вернуть из cloud-init metadata. Сравните diff user-audit/ каталогов.

Группа adm на Ubuntu читает /var/log/syslog если rsyslog ещё кладёт файлы 640 adm. Это не sudo, но лишний доступ к auth.log. Инвентаризируйте getent group adm. Для journal используйте systemd-journal, не раздувайте adm.

root без пароля (NP) на cloud-образе: консоль гипервизора может пускать по ключу провайдера. Смените пароль root в сейф или заблокируйте пароль, оставьте только консольный ключ провайдера по политике. Не оставляйте пустой пароль root.

Повторяемость: тот же чеклист в ansible community.general.users факты + assert. Разовый audit через полгода тухнет.

Не забудьте технические учётки CI (gitlab-runner, jenkins). Их ключ в authorized_keys deploy — часть аудита. Срок жизни ключа и CIDR источника — в той же таблице, что люди. Иначе «пользователей почистили», runner с ключом 2019 жив.

getent shadow не для отчёта. Только passwd -S.

Сверьте /etc/adduser.conf DIR_MODE: новые home не должны рождаться как 777. На Ubuntu обычно 0750 или 0755 — зафиксируйте в эталоне, иначе каждый adduser плодит лишний other+rx на home с ключами.

Как проверить, что проблема устранена

Аудит выполнен, если в заявке лежат passwd.txt, passwd-S.txt, lastlog.txt, sudoers.txt и таблица с решениями. Повтор через квартал. Для уже применённых lock — проверки из статьи про неиспользуемые учётки. admin SSH жив.

Если не помогло

  • getent медленный: sssd, не «passwd сломан».
  • lastlog пустой на 24.04: пакет lastlog vs lastlog2 — смотрите last/loginctl.
  • sudo -l пустой при членстве sudo: sudoers Host_Alias.
  • Ключи в AuthorizedKeysCommand — каталог, не файл home.

Профилактика

  • Квартальный прогон чеклиста.
  • Offboarding = обязательные поля таблицы.
  • Запрет группы docker на проде.
  • auditd watches на passwd/sudoers.

FAQ

UID_MIN

Смотрите /etc/login.defs UID_MIN (обычно 1000). Не гадайте.

root в lastlog

Консольные входы. SSH root должен быть запрещён.

NP и ключи

Пароль UNIX для sudo всё равно желателен. NP+NOPASSWD+ключ = один украденный файл = root.

Как учесть сервисных с UID 1001

Столбец «владелец unit». Не lastlog.

Windows-админ спрашивает «аналог AD users»

Это и есть. Нет GUI — таблица из getent.