Свежая учётка в /etc/passwd: как заметить и что делать дальше
Если атакующий закрепился на сервере, он редко ограничивается одним бэкдором в приложении — слишком легко потерять доступ после чистки. Один из самых живучих приёмов — завести собственную учётную запись в системе: иногда с UID 0, чтобы получить права root под другим именем, иногда с именем, похожим на служебную учётку, чтобы не бросаться в глаза. Такая запись переживает перезапуск сервисов и смену паролей от панели и продолжает пускать хозяина обратно через SSH или su. Ниже — как регулярно проверять /etc/passwd и /etc/shadow на подобные находки, какие признаки должны насторожить и что делать при обнаружении.
Содержание
Почему это работает
Создать учётку — не эксплойт под конкретную версию ядра, а одна команда useradd, доступная любому, кто хоть раз получил root: через уязвимость в приложении, украденный SSH-ключ, слабый пароль в sudo. После этого атакующий заходит по паролю или своему ключу, даже если вы пересобрали уязвимое приложение и сменили все пароли, о которых знали.
Такая учётка выглядит как легитимный системный объект: администраторы привычно проверяют веб-логи и cron, но не всегда построчно сверяют /etc/passwd с тем, что было неделю назад — тем более если имя подобрано похожим на существующее (syslog, system, sshd-user, backup2). И UID 0 не обязателен: учётка с обычным UID, добавленная в sudo/wheel, даёт те же права, но выглядит скромнее.
На что смотреть в /etc/passwd
Формат строки: имя:x:UID:GID:комментарий:домашний_каталог:shell.
UID 0 у не-root пользователя. В норме UID 0 принадлежит только root. Любая другая строка с нулевым UID — это полноценный root под другим именем:
awk -F: '$3 == 0 {print}' /etc/passwd
Больше одной строки в выводе — тревога.
Служебный UID, но рабочий shell. Системные учётки обычно занимают низкие UID (до 999–1000, смотрите /etc/login.defs) и почти всегда имеют /usr/sbin/nologin или /bin/false вместо shell. Найдите несостыковки:
awk -F: '($3 < 1000) && ($7 !~ /nologin|false/) {print}' /etc/passwd
Домашний каталог не на месте. /var/tmp, /dev/shm, /opt/.hidden вместо /home/<имя> или профильного пути служебной учётки — повод присмотреться.
Имя похоже на системное, но им не является. Сверяйте с тем, что реально устанавливало учётку:
getent passwd имя_пользователя
grep имя_пользователя /var/log/dpkg.log* 2>/dev/null
Если учётка есть, но ни один пакет её не заводил и вы её не создавали — это чужеродный объект.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНа что смотреть в /etc/shadow
Формат: имя:хэш:дата_смены:.... Доступен только root.
Пустое поле пароля. имя::... означает вход без пароля вообще — критическая находка сама по себе:
awk -F: '($2 == "") {print $1}' /etc/shadow
**! или * не значит "недоступно".** Это блокирует вход по паролю, но если учётка состоит в sudo/wheel и имеет SSH-ключи в authorized_keys — доступ всё равно есть.
Дата последней смены пароля. Третье поле — число дней с эпохи Unix. Недавняя дата у "старой" служебной учётки, которой пароль в принципе не нужен, — след:
chage -l имя_пользователя
Как проверять регулярно
Разовая проверка руками — хорошо, но пользу даёт регулярность: закладку обычно находят через недели, когда логи уже перезаписаны. Простой вариант без дополнительного софта — ежедневный снимок и сравнение через cron:
#!/bin/bash
# /usr/local/bin/check-passwd-diff.sh
SNAP_DIR=/var/lib/passwd-snapshots
mkdir -p "$SNAP_DIR"
TODAY="$SNAP_DIR/passwd-$(date +%F).txt"
cp /etc/passwd "$TODAY"
YESTERDAY=$(ls -1 "$SNAP_DIR" | grep -v "$(date +%F)" | tail -1)
if [ -n "$YESTERDAY" ]; then
DIFF=$(diff "$SNAP_DIR/$YESTERDAY" "$TODAY")
[ -n "$DIFF" ] && echo "Изменения в /etc/passwd:" && echo "$DIFF"
# здесь же — отправка в свой канал уведомлений: email, telegram-бот, вебхук
fi
find "$SNAP_DIR" -type f -mtime +30 -delete
15 3 * * * /usr/local/bin/check-passwd-diff.sh >> /var/log/passwd-diff.log 2>&1
Не заменяет полноценный HIDS, но не требует настройки и не пропустит новую строку.
Надёжнее — auditd: он пишет в лог факт открытия файла на запись, с процессом и пользователем-инициатором:
auditctl -w /etc/passwd -p wa -k passwd_changes
auditctl -w /etc/shadow -p wa -k shadow_changes
auditctl -w /etc/sudoers -p wa -k sudoers_changes
Чтобы правила пережили перезагрузку, вынесите их в /etc/audit/rules.d/passwd-watch.rules. Поиск по метке: ausearch -k passwd_changes. Подробнее о настройке — в статье аудит логов сервера через auditd. Если уже есть система контроля целостности файлов (AIDE, Tripwire) — добавьте в неё /etc/passwd, /etc/shadow, /etc/group, /etc/sudoers.
Что делать при обнаружении подозрительной учётки
Главный принцип: не удаляйте находку сразу. Удалённая учётка — это потерянные улики: кто ею пользовался, когда заходил, что создавал в домашнем каталоге. Без этого расследование превращается в гадание.
1. Зафиксируйте состояние. Скопируйте /etc/passwd, /etc/shadow, /etc/group, /etc/sudoers и /etc/sudoers.d/ на другую, заведомо не скомпрометированную машину. Сохраните домашний каталог находки целиком:
tar czf /root/investigation/suspicious-user-home.tar.gz -C /home имя_пользователя
2. Заблокируйте вход, не удаляя учётку:
usermod -L имя_пользователя
usermod -s /usr/sbin/nologin имя_пользователя
Если это UID 0 — не трогайте сам UID до завершения анализа: его смена сразу после блокировки может сместить владельца уже созданных файлов.
3. Найдите SSH-ключи. Проверьте ~/.ssh/authorized_keys находки и всех остальных пользователей, включая root — прописанный там чужой ключ работает независимо от пароля учётки:
find / -name authorized_keys -exec ls -la {} \; 2>/dev/null
cat /home/имя_пользователя/.ssh/authorized_keys 2>/dev/null
4. Проверьте sudoers и группы с повышенными правами. Не только /etc/sudoers, но и весь /etc/sudoers.d/, а также членство в sudo, wheel, docker (доступ в docker фактически равносилен root):
grep -R "имя_пользователя" /etc/sudoers /etc/sudoers.d/ 2>/dev/null
groups имя_пользователя
5. Найдите cron-задачи этой учётки — персональные crontab легко упускаются при беглом просмотре:
crontab -u имя_пользователя -l
ls -la /var/spool/cron/crontabs/ 2>/dev/null
Reverse shell по расписанию от имени свежесозданного пользователя — частая связка, разобрана отдельно в статье про reverse shell в cron у пользователя, которого никто не заводил.
6. Проверьте, что ещё создавал этот пользователь:
find / -user имя_пользователя 2>/dev/null
7. Смените пароли и ключи, к которым сервер имел доступ — базы данных, внешние API, панели, а также ключи, которыми сервер сам подключался к другим машинам (бэкапы, деплой, мониторинг). Считайте их скомпрометированными.
8. Только после сбора улик — удаляйте:
userdel -r имя_пользователя
Если находка не единственная или есть сомнения в целостности системы — надёжнее не вычищать построчно, а поднять окружение заново из чистого образа и перенести только проверенные данные. Общий порядок действий при взломе — в статье взломали сервер: пошаговый план.
Типичные ошибки при разборе находки
Самая частая — удалить учётку сразу, из желания немедленно "закрыть дыру". Это не закрывает дыру: способ проникновения остаётся неизвестным, и через день-два появится новая закладка под другим именем.
Вторая — остановиться на первой находке. Если в системе одна подозрительная учётка, разумно считать, что есть и другие точки закрепления: cron-задачи без привязки к новому пользователю, изменённые бинарники, добавленные systemd-юниты, правки в /etc/rc.local. Одна находка — это одна точка, а не вся картина.
Третья — не задокументировать находку: какие признаки были, через что вошли, сколько учётка просуществовала незамеченной. Такой разбор — база для следующего инцидента. Базовый синтаксис работы с пользователями и группами — в статье управление пользователями и группами Linux.
Четвёртая — слепо доверять стандартным утилитам после компрометации с root-доступом: атакующий с root мог подменить ls, ps, netstat, чтобы они скрывали его следы. Встречается реже, чем простое создание пользователя, но при серьёзных подозрениях стоит сверить хэши бинарников с эталонными (debsums на Debian/Ubuntu, rpm -Va на RHEL-based) или проверить систему с чистого live-образа.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
UID 0 у второго пользователя — это всегда взлом?
Практически всегда. Легитимных причин заводить второго пользователя с UID 0 крайне мало. Если сами такого не делали — считайте компрометацией.
Как часто проверять /etc/passwd без auditd?
Ежедневный снимок через cron — разумный минимум. Для критичных систем лучше сразу auditd или монитор целостности — он реагирует почти сразу, а не раз в сутки.
Учётку заблокировали, а атакующий всё равно заходит — как так?
Есть другая точка входа: ключ в чужом authorized_keys, отдельный cron-бэкдор, изменённый сервис. Пройдитесь по остальным пунктам раздела про обнаружение.
Можно ли просто откатить сервер из бэкапа вместо разбора?
Можно, если бэкап заведомо сделан до компрометации и понятно, через что произошёл вход — иначе есть риск восстановить ту же уязвимость.
Нужно ли сообщать о находке провайдеру сервера?
Если сервер стал плацдармом для атак на других (спам, сканирование портов) — да: это защищает от блокировки по чужим жалобам.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →