Получить доступ — половина дела; вторая половина в том, чтобы его не потерять. Поэтому почти всё автоматизированное вредоносное программное обеспечение первым делом обеспечивает себе повторный запуск: после перезагрузки, после удаления файла, после смены пароля. Отсюда типичная история — «почистили, через два дня вернулось».

Мест, где это устраивается, не так много, и все они проверяются за несколько минут. Ниже — полный обход по порядку.

1. Ключи SSH

Самый простой способ вернуться: строка в authorized_keys переживает смену пароля, обновление системы и перезагрузку.

sudo find /home /root -name authorized_keys -exec ls -l {} \; -exec cat {} \;

Каждая строка — чей-то постоянный доступ. Если не можете сказать, чей именно, считайте чужим. Обратите внимание и на комментарий в конце строки: он произвольный, и совпадение с вашим именем ничего не доказывает.

2. Задания cron всех пользователей

Проверять надо не только свой crontab:

for u in $(cut -f1 -d: /etc/passwd); do echo "== $u"; sudo crontab -u "$u" -l 2>/dev/null; done
sudo ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
sudo cat /etc/crontab

Признаки, на которые стоит смотреть: строки @reboot, длинные закодированные команды, обращения к curl или wget с последующей передачей в оболочку, запуск чего-либо из /tmp, /dev/shm или /var/tmp. Из этих каталогов ничего штатного не запускается.

3. Таймеры и службы systemd

Современный аналог cron, и проверяют его заметно реже:

systemctl list-timers --all
systemctl list-units --type=service --state=running
sudo ls -la /etc/systemd/system/ /run/systemd/system/

Отдельно — пользовательские службы, которые работают без прав root и не попадают в общий список:

systemctl --user list-units --type=service
sudo ls -la /home/*/.config/systemd/user/

Ещё одна деталь: включённая для пользователя задержка выхода (loginctl enable-linger) позволяет его службам работать без активного сеанса. Проверяется командой loginctl list-users.

4. Файлы автозапуска оболочки

Код, дописанный в конец файла запуска оболочки, выполняется при каждом входе:

sudo tail -5 /root/.bashrc /root/.profile /home/*/.bashrc /home/*/.profile
sudo ls -la /etc/profile.d/

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

5. ld.so.preload

Файл, заставляющий систему подгружать указанную библиотеку в каждый запускаемый процесс. Штатно он не создаётся ни при каких обстоятельствах:

ls -l /etc/ld.so.preload

Его наличие — практически однозначный признак серьёзной компрометации, и такая библиотека обычно скрывает и файлы, и процессы, и сетевые соединения. Всё, что вы увидите на такой машине дальше, доверия не заслуживает.

6. Хуки пакетного менеджера

Способ, о котором вспоминают редко: apt умеет выполнять команды до и после каждой операции с пакетами.

sudo ls -la /etc/apt/apt.conf.d/
sudo grep -r 'DPkg::Pre-Invoke\|DPkg::Post-Invoke\|APT::Update' /etc/apt/apt.conf.d/

Такой хук срабатывает при каждой установке обновлений — то есть регулярно и от root.

7. Сообщение дня в Ubuntu

Каталог /etc/update-motd.d/ содержит исполняемые сценарии, которые запускаются при каждом входе по SSH и формируют приветственный текст. Место удобное именно тем, что выглядит служебным:

sudo ls -la /etc/update-motd.d/

8. Отложенные задания at

sudo atq
sudo ls -la /var/spool/cron/atjobs/ 2>/dev/null

Механизм старый и редко используемый, поэтому и проверяемый реже всего.

Порядок действий, если что-то нашлось

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

  1. Сохранить копию файла или задания и его время изменения.
  2. По этому времени посмотреть в логи веб-сервера и в auth.log — что происходило в ту же минуту. Обычно там и находится точка входа.
  3. Проверить все восемь мест из списка, а не только то, где нашлось. Закладку почти никогда не оставляют в единственном экземпляре.
  4. Только после этого чистить и закрывать саму уязвимость.

Знать, как выглядит норма

Главная сложность этой проверки не в командах, а в том, что незнакомая строка в списке заданий не выглядит подозрительной, если вы не помните, каким этот список был раньше. На сервере, который настраивали не вы или настраивали год назад, отличить своё от чужого почти невозможно.

Отсюда практический вывод: снимок «как есть» имеет смысл сделать сегодня, пока сервер в порядке. Список заданий cron, таймеров, ключей и служб на здоровой машине — это тот эталон, с которым потом сравнивают. Собранный и сохранённый с историей, он превращает поиск закладки из многочасового занятия в сравнение двух списков. Как это выглядит — на страницах демо ниже.