
Это вторая часть статьи про Linux Incident Response — разбор live response на работающем Linux-хосте с подозрением на компрометацию.
Если вы не читали первую часть, лучше начать с неё: в ней разобрали принципы расследования, изоляцию хоста, trusted toolkit, фиксацию исходного состояния, сетевые соединения и процессы. Без этого контекста часть команд и логика дальнейшего анализа будут менее понятны.
Первая часть здесь.
В этой части процесс идет далее — к менее изменчивым артефактам. Рассмотрим механизмы закрепления и следы на диске: systemd-сервисы и timers, cron, автозапуск, пользователи, группы, пакеты, логи, kernel-артефакты. В финале расскажем о построении таймлайна, оформлении IOC и действия с системой после завершения расследования.
Шаг 6. Службы и сервисы
sudo systemctl list-units --type=service --state=running
Даёт полный список запущенных сервисов. Задача — найти то, что не вписывается в нормальную активность системы. На тестовой машине среди запущенных сервисов один привлекает внимание: sysupdate.service с описанием «System Update Service». Звучит легитимно, но атакующие намеренно называют свои сервисы как системные, чтобы усложнить обнаружение.

systemctl status дает детали:

А unit-файл их подтверждает. Сервис в статусе enabled, а Restart=always. Это указывает на закрепление, поскольку если убить процесс вручную, systemd его перезапустит. Команда kill не даст результата. Main PID совпадает с тем что мы нашли через ss, в CGroup прямо видна команда nc -lp 4444.
В данном случае это просто listener. В реальных сценариях на этом месте можно было бы обнаружить ExecStart=/usr/bin/nc.traditional -l -p 4444 -e /bin/sh — bind shell, когда атакующий подключается к порту 4444 и получает командную строку.
journalctl -u sysupdate.service даст хронологию запуска для таймлайна инцидента.

Но сервис может быть не в статусе running на момент анализа, а запускаться по таймеру. Поэтому таймеры надо изучить командой:
systemctl list-timers --all
sudo find /etc/systemd/system -name "*.timer"
Шаг 7. Cronjobs
Задачи cron — классический способ закрепления. Задача выполняется автоматически по расписанию, не требует активного присутствия атакующего и легко теряется среди легитимных системных задач.
В Linux есть несколько мест с задачами для cron:
# Системный crontab
sudo cat /etc/crontab
# Пользовательские crontabs
sudo ls -la /var/spool/cron/crontabs/
sudo cat /var/spool/cron/crontabs/*
# Системные директории
sudo ls -la /etc/cron.d/
sudo ls -la /etc/cron.hourly/
sudo ls -la /etc/cron.daily/
sudo ls -la /etc/cron.weekly/
sudo ls -la /etc/cron.monthly/
# Содержимое всех файлов в cron.d
sudo grep -r "" /etc/cron.d/
#Анакрон
sudo cat /etc/anacrontab
В отличие от классического cron, Anacron гарантирует, что пропущенные из-за выключения или спящего режима компьютера задачи выполнятся при первом включении системы.

В /etc/crontab есть находка. Два отдельных правила для одного файла — @reboot запускает его при каждой загрузке системы, * * * * * запускает каждую минуту. Путь /tmp/.update достаточно тривиален, потому что /tmp/ доступен на запись всем, а точка в начале имени файла делает файл скрытым от обычного ls.
При проверке cron надо смотреть не только на содержимое записей, но и на временны́е метки и права файлов. ls -la показывает сразу оба артефакта. Дата последнего изменения /etc/crontab в подозрительное время — вклад в timeline инцидента.
Права доступа — отдельная история: /etc/crontab должен быть доступен на запись только root (-rw-r--r--). Если права шире — это либо misconfiguration, которую атакующий мог использовать для повышения привилегий, либо намеренное изменение чтобы закрепиться без root. То же касается файлов которые cron запускает: скрипт в /tmp/.update с правами rwxrwxrwx означает что любой пользователь системы может подменить его содержимое и получить выполнение от root через минуту.
Найденный подозрительный файл можно исследовать с помощью команд:
ls -la /tmp/.update
sha256sum /tmp/.update
strings /tmp/.update | grep -E 'https|bash|exec|curl|wget'
file /tmp/.update

Контрольная сумма пойдет в TI, strings даст представление о назначении файла и также данные для TI, ls -la покажет права и временну́ю метку. В нашем случае -rwxr-xr-x 1 root root, Jun 24 15:07 — файл создан в момент компрометации, принадлежит root, исполняемый. Поскольку файл вредоносный условно, вывод strings показывает sleep, nanosleep и легитимные URL GNU — это копия системного sleep, ничего вредоносного. На реально вредоносном файле здесь можно было бы найти IP-адреса C2, URL, имена функций типа execve, system, popen.
file дает тип — ELF 64-bit.
Шаг 8. Другие механизмы автозапуска
Это скрипты или команды, выполняемые автоматически при загрузке системы или входе пользователя в систему. Этим они отличаются от cron, которые запускаются по расписанию.
sudo ls -la /etc/init.d/
/etc/init.d/ — legacy-механизм запуска сервисов, предшественник systemd. На современных системах почти вытеснен, но проверять нужно.
sudo find /home -name "*.desktop" 2>/dev/null
Скрипты автозапуска для desktop-окружений. Выполняются когда пользователь логинится в систему.

На нашей машине в домашней директории пользователя backdoor обнаружен подозрительный файл. Поле Exec запускает скрипт из домашней директории пользователя backdoor. Изучим файл подробнее.

Каждый раз когда backdoor логинится в систему, будет скачиваться скрипт с внешнего сервера и выполняться в bash.
Удалённый адрес и название файла должно уйти в TI, а если адрес принадлежит другому хосту в инфраструктуре компании — это следующий кандидат на анализ.
sudo find /home \( -name ".profile" -o -name ".bashrc" \) | \ xargs grep -l "curl\|wget\|nc\|bash -i" 2>/dev/null
Файлы .bashrc и .profile выполняются автоматически при каждом открытии терминала или логине пользователя. Атакующий может дописать в конец любого из них вредоносную команду — и она будет выполняться незаметно каждый раз когда пользователь открывает терминал.
sudo find /home -name "authorized_keys" | xargs cat 2>/dev/null
~/.ssh/authorized_keys — этот файл содержит список публичных ключей которым разрешён SSH-доступ к аккаунту без пароля. Атакующий может добавить сюда свой ключ и получить вход в любое время, если конфигурация sshd разрешает аутентификацию по ключам.
Шаг 9. Пользователи, группы и привилегии
Использование учетных записей — еще один способ закрепления. Кроме того, при наличии достаточных привилегий у аккаунта атакующий способен значительно развить свой успех.
sudo cat /etc/passwd
/etc/passwd — первое место, где смотрим на пользователей. Формат каждой строки: имя:пароль:UID:GID:описание:домашняя_директория:shell. Нас интересуют пользователи с интерактивным shell (/bin/bash или /bin/sh) в первую очередь. С этими shell пользователь пригоден для интерактивной сессии — системные аккаунты намеренно ограничены /usr/sbin/nologin или /bin/false.
Можно отфильтровать всех пользователей с реальным шеллом командой:
grep -v "nologin\|/bin/false\|/bin/sync" /etc/passwd

Backdoor — очевидно вредоносный аккаунт, встречавшийся ранее. В реальных инцидентах backdoor-аккаунты называют менее очевидно: support, svc-monitor, git и т.д.
Также надо обращать внимание на UID 0, кроме root:
awk -F: '$3 == 0 {print}' /etc/passwd
Следующий вопрос — какие привилегии у найденных аккаунтов. Смотрим на группу sudo в /etc/group:
sudo grep sudo /etc/group (sudo grep wheel для RHEL)

Заглянем в /etc/sudoers и /etc/sudoers.d
%sudo ALL=(ALL:ALL) ALL
Означает, что каждый юзер в группе sudo может запускать команды от любого пользователя, включая root, после ввода своего собственного пароля.
Ещё одна проверка — /etc/shadow. Аккаунт может существовать в /etc/passwd но быть заблокированным: символы * или ! в поле пароля означают что войти по паролю невозможно. Команда, выводящая аккаунты с установленным паролем:
sudo awk -F: '$2 !~ /^[*!]/ {print $1}' /etc/shadow
Атакующий мог разблокировать существующий системный аккаунт вместо создания нового — это менее заметно чем новый пользователь.
Если подозрительный аккаунт был обнаружен, целесообразно проверит историю его входов через last. last читает /var/log/wtmp и показывает историю логинов. Неудачные попытки логина смотрим отдельно:
sudo last -f /var/log/btmp (или sudo lastb на RHEL)
Шаг 10. Пакеты, файловая система и артефакты приложений
grep " install " /var/log/dpkg.log
dpkg.log фиксирует каждую операцию с пакетами: установку, удаление, обновление — с точным временем. На тестовой машине видна масса легитимных пакетов установленных 2026-06-24 в процессе развёртывания системы. Но в самом конце списка — аномалия:

Два момента. Первый — имя пакета malware. В реальности атакующие называют их менее очевидно, но принцип тот же: пакет появившийся после начальной установки системы без явной причины — подозрителен. Если необходимо, поднимите заявки на установку ПО для анализируемого хоста, чтобы установить легитимность того или иного пакета.
Второй — дата 2024-06-24 при том что вся система установлена в 2026-06-24.
Далее нужно проверить недавно измененные файлы. Следует исключать из проверки /proc и /sys — там изменений всегда будет много. Команда:
sudo find / -mtime -3 -type f \
-not -path "/proc/*" \
-not -path "/sys/*" 2>/dev/null | head -30
-mtime -3 показывает файлы изменённые за последние 3 дня. Порог подбирается под контекст: если система работает месяц без обновлений, свежеизменённый файл в /usr/bin — немедленный флаг.
sudo find / -perm -4000 -type f 2>/dev/null
Эта команда ищет файлы с установленным SUID-битом. SUID-бит позволяет запускать файл с правами его владельца, а не запускающего пользователя. Нужно обращать внимание на SUID-файлы в нестандартных местах — /tmp, /home, /opt.

В нашем выводе два нестандартных файла: /mnt/usb/bin/sudo — наш trusted sudo, которому мы сами выставили бит, и /opt/VBoxGuestAdditions-7.0.26/bin/VBoxDRMClient — легитимный компонент VirtualBox.
sudo find /opt /tmp /var/tmp /home -name ".*" -type f 2>/dev/null
Поиск скрытых файлов в пользовательских директориях. Как известно, точка в начале названия файла делает файл скрытым от обычного ls. На некоторых серверах вывод может быть большой. Чтобы облегчить работу, можно использовать фильтры по времени -time и -min.
Отдельный пункт — артефакты приложений. Поскольку приложений много, как пример здесь можно привести два артефакта: .viminfo и ~/.mozilla/firefox/ .
sudo find /home -name ".viminfo" 2>/dev/null
sudo find /home -type d -path "*/.mozilla/firefox" 2>/dev/null
.viminfo хранит историю команд в Vim. Также можно попытаться поискать подобные файлы для других текстовых редакторов: .nano_history и .emacs.
В реальном расследовании .bash_history и .viminfo могут содержать прямые следы действий атакующего: команды которые он выполнял, файлы которые редактировал, IP-адреса к которым подключался. Браузерные артефакты в ~/.mozilla/firefox/ или ~/.config/google-chrome/ — история посещений, загрузки, cookies — особенно ценны, если линуксовый хост — это десктоп, а не сервер.
Шаг 11. Логи
Первое, что нужно определить на незнакомой системе — какой механизм логирования используется. На Debian 13 по умолчанию установлен только systemd-journald без rsyslog. Это означает, что привычных /var/log/auth.log и /var/log/syslog не существует — все логи идут в бинарный journal и читаются через journalctl. На системах с rsyslog оба механизма работают параллельно. Итоговый набор источников логов зависит от политики логирования конкретной организации. Помимо journald и rsyslog на системе может быть настроен auditd. Если auditd настроен с правилами (/etc/audit/audit.rules) — это золотой источник для расследования. Короче говоря, первый шаг — выяснить, как работает логирование.
Аутентификация и управление пользователями
sudo journalctl _COMM=useradd --no-pager
sudo journalctl _COMM=sudo --no-pager
journalctl _COMM=useradd фильтрует все события создания пользователей. В нашем выводе хронология сразу показывает ивент:

Пользователь backdoor создан Jun 24 15:07:28 — вклад в таймлайн инцидента. Поле from показывает терминал с которого была выполнена команда. none означает что пользователь создан не интерактивно — скриптом или сервисом.
journalctl _COMM=sudo фиксирует все команды выполненные через sudo: пользователь, рабочая директория, точная команда.
Cron
sudo journalctl -u cron --no-pager
Journald подтверждает, что обнаруженный ранее /tmp/.update выполняется каждую минуту от root:

Сервисы
Поведение подозрительных сервисов можно посмотреть командой:
sudo journalctl -u sysupdate.service --no-pager
Некоторые службы не будут писать все свои сообщения в journald. Например, веб-сервер Apache не будет писать в journald по умолчанию, он пишет в собственные файлы в /var/log/apache2/. Эта директория будет содержать два файла: access.log и error.log. Просматривать эти файлы и файлы других подобных служб лучше через cat, less, или grep.
Другие способы фильтрации
Для фильтрации по времени через journald используйте различные флаги, такие как --since или -S и --until или -U:
sudo journalctl -S "2026-06-24 00:00:00" -U "2026-06-26 02:29:59"
Работает также более простой способ, с указанием «today», «yesterday», «N hours ago».
Важно помнить, что journald хранит временны́е метки в UTC внутри бинарного журнала. Но journalctl при выводе автоматически конвертирует в локальный часовой пояс системы.
Именно поэтому в начале расследования важна команда timedatectl — она показывает и системное время, и UTC. Тем не менее, можно вывести лог без поправки на часовой пояс с помощью флага --utc.
Хочется еще раз подчеркнуть важность понимания работы логирования перед просмотром журналов. Например, при настроенном auditd можно оперировать ausearch и aureport.
На rsyslog-системах логи ротируются и сжимаются: auth.log → auth.log.1 → auth.log.2.gz. Обычный grep не читает сжатые файлы — нужен zgrep:
# Поиск по всем логам включая архивные
zgrep -i "backdoor" /var/log/auth*
zgrep "session opened" /var/log/auth*
zgrep "Failed password" /var/log/auth*
Kernel-логи и признаки руткита ядра
В начале статьи упоминался kernel-level compromise. Например, атакующий мог внедрить свой kernel object (.ko) через insmod. Если он подтверждается — live response теряет смысл. Результаты любых команд могут быть искажены на уровне системных вызовов. Единственный надёжный путь — offline-анализ с загрузкой с внешнего носителя.
Можно попытаться установить факт такого вмешательства командами:
sudo journalctl -k | grep -i "module\|taint\|loading"
Ожидая вывод
kernel: loading out-of-tree module taints kernel.
kernel: module verification failed: signature and/or required key missing
Посмотреть все загруженные модули прямо сейчас:
lsmod
Подозрительный модуль можно изучить подробнее:
modinfo <имя_модуля>
Шаг 12. Построение таймлайна и сбор IOC
Таймлайн — это артефакт расследования, который сводит все найденные события в единую хронологию. Строится, в первую очередь, на основе лога действий аналитика, записанного script или другим способом, хоть на бумажке (лучше не надо). Выглядит это примерно так:
….
Jun 24 14:06 — установлены гостевые дополнения VirtualBox
Jun 24 15:07 — создан backdoor-аккаунт (from=none)
Jun 24 15:07 — установлен пароль для backdoor
Jun 24 15:07 — backdoor добавлен в группу sudo
Jun 24 15:07 — запущен sysupdate.service
Jun 24 15:07 — в /etc/crontab добавлены вредоносные записи
Jun 24 15:07 — создан /tmp/.update
Jun 24 15:07 — создан autostart-скрипт в /home/backdoor/
Jun 24 15:12 — сетевая изоляция хоста
….
Индикаторы компрометации оформляются в структурированный список:
# Файлы
SHA256(/tmp/.update) = 0637e6d47579929cb72efa46f361861b...
# Аккаунты
Backdoor account: backdoor / UID=1002 / GID=1002 / sudo group
# Persistence
Service: sysupdate.service — ExecStart=/bin/bash -c 'nc -lp 4444'
Cron: @reboot root /tmp/.update
Cron: * * * * * root /tmp/.update
Autostart: /home/backdoor/.config/autostart/dev-setup.desktop
# Сеть
Port: TCP 4444 LISTEN
URL: http://192.168.56.105/shell.sh
# Пакеты
Package: malware:amd64 1.0 (2024-06-24 12:00:00)
Каждый из этих артефактов имеет конкретное применение. Хэши файлов загружаются в VirusTotal и проверяются по базам threat intelligence — если хэш известен, сразу становится понятно с каким инструментом или группой мы имеем дело. Хэши и строки вредоносных файлов становятся основой YARA-правил для threat hunting по другим хостам инфраструктуры. IP-адреса и домены блокируются на периметре. Паттерны поведения становятся корреляционными правилами в SIEM.
Шаг 13. Действия после IR
Систему нельзя просто вычистить и вернуть в эксплуатацию. Мы нашли backdoor-аккаунт, malicious service, cron-задачи, autostart-скрипт — но можем ли мы утверждать что нашли всё? Нет. Атакующий мог оставить десятый persistence механизм который мы не обнаружили. Именно поэтому третий принцип расследования, сформулированный в начале статьи, звучит так: цель IR — понять, а не вылечить.
Правильная последовательность действий после завершения расследования:
1. Восстановление из резервной копии. Переразвёртывание системы из бэкапа сделанного до момента компрометации. Таймлайн даёт нам точку отсчёта: компрометация произошла в районе Jun 24 — значит, нужна резервная копия строго до этого времени. Бэкап после точки компрометации потенциально уже содержит артефакты атаки.
2. Смена всех секретов. Пароли всех пользователей системы, SSH-ключи, API-токены, credentials сервисов которые были доступны с этого хоста. Атакующий мог прочитать их из памяти, конфигурационных файлов или истории команд. Ну и в целом, требуется проверка конфигурации системы. Вероятно, именно мисконфиг, типа дефолтного пароля, мог послужить причиной успешной атаки.
3. Проверка соседних систем. Timeline показывает что атакующий работал с Jun 24 15:07. За это время он мог использовать скомпрометированный хост как плацдарм для атаки на другие машины в сети. Все системы к которым имел доступ этот хост — под подозрением.
4. Усиленный мониторинг после восстановления. Собранные IOC загружаются в SIEM и EDR. Если атакующий вернётся — он будет обнаружен немедленно.
Мини-плейбук
0. Изолировать хост от сети (EDR / VLAN / NAC)
1. Подключить trusted toolkit, переключить PATH
2. Запустить script для логирования сессии
3. Зафиксировать состояние системы (uname, hostnamectl, timedatectl)
4. Сеть: ip a, ss -tulnp, ss -tunp
5. Процессы: ps aux, pstree, lsof
6. Сервисы: systemctl list-units --type=service --state=running
7. Cron: /etc/crontab, /var/spool/cron/crontabs/, /etc/cron.*
8. Autostart: /etc/init.d/, ~/.config/autostart/, ~/.bashrc, ~/.profile
9. Пользователи: /etc/passwd, /etc/group, /etc/sudoers, артефакты пользователей и приложений
10. Пакеты и файлы: dpkg.log, find -mtime, find -perm -4000
11. Логи: journalctl / auth.log / syslog / audit.log
12. Построить timeline, собрать IOC
13. Восстановить из бэкапа до точки компрометации
14. Сменить все секреты
15. Загрузить IOC в SIEM/EDR, проверить соседние хосты
Чего не делать:
Не перезагружать систему до завершения анализа волатильных данных
Не устанавливать пакеты через apt во время расследования
Не писать результаты на диск жертвы
Не возвращать систему в эксплуатацию
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
-15% на заказ нового VDS — HABRFIRSTVDS.