Реагирование на инциденты — отдельная дисциплина: канонический жизненный цикл описан в NIST SP 800-61, а OWASP дополняет его читшитами по расследованию инцидентов и сохранению улик. Разница между «отрубили на час» и «висело в чёрных списках полгода» почти всегда не в том, кто взломал, а в том, что делали первые два часа после обнаружения.
Дано по состоянию на октябрь 2026; версии инструментов (Loki, Falco, утилиты ядра) сверяйте на момент применения — команды в статье рассчитаны на типичный LAMP/LEMP-хост с GNU-утилитами (ss, find, grep, journalctl).
Часть I. Фреймворк: инцидент как процесс, а не подвиг
1. Четыре стадии NIST SP 800-61
Каноническая «Инструкция по реагированию на компьютерные инциденты» (NIST SP 800-61) разбивает жизнь вокруг взлома на четыре фазы. Полезно воспринимать её не бюрократию, а чек-лист против паники:
| Стадия | Вопрос | Типичная ошибка |
|---|---|---|
| Preparation (до взлома) | Есть ли бэкапы, неизменяемые логи, план и контакты? | «Разберёмся по факту» — нет ни логов, ни чистой копии |
| Detection & Analysis | Что реально скомпрометировано, с какого момента? | Принять ложное срабатывание за рут-компромет и сжечь прод |
| Containment, Eradication & Recovery | Остановить ущерб → убрать след → вернуться в норму | Удалить симптом (файл), не тронув причину (уязвимость) |
| Post-Incident Activity | Что сработало, что чинить в превенции? | Не обновить план → тот же взлом через месяц |
Вся эта статья — практическое разворачивание трёх средних стадий для владельца сайта. Первая (подготовка) логически замыкает все предыдущие выпуски серии.
2. Роли и «военная» дисциплина
Даже в одиночку ведите запись: единый лог инцидента с таймстампами (время, действие, кто сделал, результат), где каждое решение помечено временем. Это спасает от двух бед: вы забываете, что уже отключали (ss чист после перезагрузки?), и вы не можете доказать регулятору или владельцу, что действовали добросовестно. Назначьте одного ответственного за решение «выключаем/не выключаем» — иначе в чате команды прод лежит в простое сорок минут, пока двое спорят.
Часть II. Триаж: насколько всё плохо
3. Признак компрометации ≠ компрометация
Прежде чем объявлять катастрофу, соберите наблюдения. Ниже — индикаторы компрометации (IoC), сгруппированные по «весу». Один тонкий признак может быть ложным; связка из нескольких одного класса времени — почти всегда настоящая атака.
| Косвенный (проверить) | Сильный (готовиться к пересбору) | Критический (считать скомпрометированным всё) |
|---|---|---|
| Всплеск исходящего трафика без пика продаж | Webshell: eval(...), assert(...), $_GET['cmd'] в файле темы/загрузки | Rootkit, изменённые бинарники (debsums/rpm -Va не чистые) |
Подозрительные POST на /wp-login.php из одного IP | Исходящее соединение к :4444, :6697, к майнинг-пулу | В чужом authorized_keys ключ, скрытый cron-бэкдор по всей ФС |
| Новые админы в CMS, незнакомые записи | Подмена сертификата/ключа (SSL) без вашей команды | В логах аутентификации — ваш реальный вход под чужим IP без MFA |
Изменённый .htaccess / конфиг редиректов | Закоммиченный бинарник в репозитории, запускаемый с сервера | Следы history обрываются: злодей стёр историю, зная про аудит |
Почему триаж решает: webshell в публичном каталоге загрузок CMS и утёкшая база с паспортами — это разные законы, разные сроки, разные коммуникации. Первый — «почистить и залатать»; второй — «не включать, пока не уведомил регулятора и не доказал чистоту».
4. Часы решают всё: зафиксируйте время и включите точную синхронизацию
Самая частая потеря — рассинхронизация часов при построении таймлайна. До сбора логов:
# Убедитесь, что время на хосте доверяемое (NTP/chrony), и зафиксируйте разброс
timedatectl status
chronyc sources -v 2>/dev/null || ntpq -p 2>/dev/null || echo "нет NTP — таймлайн будет приблизительным"
# Зафиксируйте «сейчас» как якорь для последующих find -newermt
date -u +"%Y-%m-%dT%H:%M:%SZ" > /evidence/incident-timestamp-utc.txt
cat /evidence/incident-timestamp-utc.txt
Все последующие find -newermt и фильтры логов считайте в UTC, а не в локальном времени браузера — иначе сдвиг на летнее время раздвинет таймлайн на часы и вы отбросите настоящий вектор.
Часть III. Сдерживание: остановить, не сломав
5. Не выключайте сервер сразу
Интуитивное «обесточить» — плохой первый ход, если только не идёт активное шифрование базы в реальном времени. До обесточивания вы теряете летучие данные, которые больше не восстановить: активные TCP-соединения (куда льются данные?), процессы в памяти (имя майнера, путь к бэкдору), переменные окружения (секреты), содержимое /dev/shm. Снимите сначала volatile-состояние:
mkdir -p /evidence && cd /evidence
# Кто с кем соединён и какими процессами
ss -tunap > connections.txt
# Процессы + дерево
ps auxwwf > processes.txt
# Что открыто у подозрительных PID (подставьте из ss/ps)
# lsof -p 1234 > fd-1234.txt
# Сетевое состояние в динамике (короткий срез)
# netstat -antp > netstat.txt # если ss мало
# Соединения извне к вашим портам и попытки брутфорса — см. журнал безопасности
Только после этого выбирайте режим сдерживания.
6. Выберите уровень сдерживания под триаж
| Ситуация | Правильное сдерживание |
|---|---|
| Webshell, точечный, вектор известен | Временный бан IP атакующего на edge (ufw/fail2ban в руководстве по серверу), изоляция одного каталога прав на запись, закрытие уязвимого URL |
| Сигнатуры по всей ФС, неясен вектор | Сервер остаётся онлайн для криминалистики, но трафик к нему гасится: временная 503 через балансировщик/.htaccess/location, база переведена в read-only |
| Подтверждённый рут, майнинг, исходящий спам-реле | Полная изоляция: закрыть исходящие (Postfix: защита от превращения в open-relay), iptables default DROP, но снимите RAM/образ диска до обесточивания |
# Точечный бан IP (пример 203.0.113.66 из резервной документации-сети TEST-NET-3)
ufw deny from 203.0.113.66 to any
# либо временная изоляция всей площадки, пока разбираетесь (оставив SSH-белый список!):
iptables -P INPUT DROP; iptables -P FORWARD DROP; iptables -P OUTPUT ACCEPT
iptables -A INPUT -p tcp --dport 22 -s <ваш_управляемый_IP> -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
Белый список на SSH — критичен: iptables -P INPUT DROP без --dport 22 ... ACCEPT оставит вас на улице, и восстановление начнётся с консоли хостинга. Не используйте боевой адрес в статьях и заметках; в командах-примерах держите плейсхолдер.
7. Смените пароли и токены на время «в изоляции», но учтите риск
Логично «перезапаролить всё» сразу, но у этой спешки есть ловушка: если бэкдор читает ваш конфиг БД или лог аутентификации, смена пароля может дать атакующему сигнал «меня заметили» и спровоцировать удаление улик. Безопасная последовательность: сначала изоляция и образы, потом ротация — и обязательно все секреты разом (см. Часть VI), а не только пароль админки.
Часть IV. Улики: снять и зафиксировать
8. Образ — не «копия файлов на глазок»
Для любого серьёзного анализа нужен целостный снимок. Минимально достаточный набор для сайта на самохостинге:
cd /evidence
# БД: логический дамп (структура + данные), не «скачать через phpMyAdmin»
mysqldump --single-transaction --routines --triggers --all-databases > db-full.sql
# Веб-корень: архив с сохранением прав/ссылок и меты
tar -czpf webroot.tar.gz -C /var/www .
# Конфигурация системы
tar -czpf etc.tar.gz /etc
9. Зафиксируйте целостность каждого артефакта (chain of custody)
Без хешей вы не сможете позже доказать, что улику не подменили (в том числе себе, через месяц, когда всё забыли):
cd /evidence
sha256sum db-full.sql webroot.tar.gz etc.tar.gz connections.txt processes.txt \
incident-timestamp-utc.txt > SHA256SUMS.txt
# Хранить /evidence лучше на отдельном томе/носителе, недоступном скомпрометированному хосту на запись
chmod -R go-rwx /evidence
Эта же идея — неизменяемость — заложена в требованиях к журналу безопасности (логирование и мониторинг): пишущий агент не должен иметь права стирать свои логи. В криминалистике тот же принцип работает против вас: злодей вычищает следы ровно так же, как предсказано там.
10. Прицельно зафиксируйте volatile-следы, специфичные для CMS/веба
cd /evidence
# Изменённые/новые файлы за окно инцидента (подставьте окно из триажа)
find /var/www -type f -newermt '2026-10-10 00:00:00' ! -newermt '2026-10-13 00:00:00' \
-printf '%TY-%Tm-%Td %TH:%TM %p\n' > changed-webfiles.txt
# Аномалии: исполняемое в загрузках, файлы с суффиксом мусора, двойные расширения
find /var/www -type f \( -path '*/uploads/*' -name '*.php' \
-o -name '*.phtml' -o -name '*.phar' -o -name '.htaccess' \) > suspicious.txt
# Подозрительные конструкции в PHP (типовые webshell-сигнатуры)
grep -RInE "eval[[:space:]]*\(|base64_decode|assert\(|\$_(GET|POST|REQUEST|COOKIE)\[|system\(|passthru|shell_exec|proc_open|popen|gzinflate|str_rot13" /var/www > webshell-grep.txt
# Персистентность: cron всех пользователей, systemd-таймеры, инициализация
for u in $(cut -f1 -d: /etc/passwd); do echo "== $u =="; crontab -l -u "$u" 2>/dev/null; done > crontabs.txt
systemctl list-timers --all > timers.txt
ls -la /etc/cron.* /var/spool/cron 2>/dev/null >> crontabs.txt
Сигнатурный grep даёт ложные срабатывания (легальный код тоже использует base64_decode) — это поиск кандидатов для ручной проверки, а не вердикт. Метод сверки «файл изменён недавно + строка с eval + POST на этот URL в access-log в ту же минуту» — вот что превращает подозрение в доказанный вектор.
Часть V. Анализ: как зашли и что изменилось
11. Таймлайн от IoC к вектору
Анализ строится «вспять по времени». У вас есть изменённый файл с метой mtime и строка-веktор в нём. Ищите в access-log и журнале безопасности, что произошло раньше этого момента и указывало на этот файл:
# Кандидат: /var/www/example.test/wp-content/uploads/x.php, mtime 2026-10-11 03:12
# Когда и кто дергал этот путь? (лог Nginx; для Apache — см. его access.log)
grep -F «/wp-content/uploads/x.php» /var/log/nginx/access.log > vector-access.txt
# Вспомогательно: POST на страницу = попытка исполнить; GET одного и того же = «проверка жива»
grep -E » (POST|PUT) /wp-content/uploads/» /var/log/nginx/access.log > suspicious-requests.txt
# Аутентификация в то же окно: успех/провалы в админку и phpMyAdmin
grep -Ei «auth|login|password|failed|denied» /var/log/auth.log 2>/dev/null > auth-window.txt
grep -F «/phpmyadmin/» /var/log/nginx/access.log > pma-window.txt
Конфигурация логов и формат (log_format) лежат в руководстве по Nginx и Apache — там же, откуда эти пути берутся.
12. Типовые векторы сайта и как они выглядят в данных
- Уязвимый плагин/тема (самый частый CMS-вектор). В логе: HTTP-запрос к имени плагина с полезной нагрузкой (
?action=..., путь к неизвестному AJAX-хендлеру), затем сразу создание/исполнение PHP в загрузках. Это ровно тот класс уязвимостей, что разбирается в OWASP Top 10:2025 (A03 инъекции, A05 неверный контроль доступа) и в практике по SQLi. - Украденные/подобранные учётки. В журнале безопасности всплеск 401, затем 200-логин с нового IP или нового User-Agent. Родственно брутфорсу и credential stuffing из детектирования.
- Скомпрометированный phpMyAdmin. Публичный доступ к
/phpmyadminбез 2FA сconfig-аутентификацией — классика; разбор защиты — в руководстве по phpMyAdmin. - Доступ по SSH/панели. Неожиданный
Accepted passwordиз настроек сервера (парольный вход вместо ключей), либо чужой ключ вauthorized_keys. - Обновление с подменой (supply chain). Зловредный пакет пришёл с npm/composer и исполняется с сервера — ищите по хеш-суммам и сравнением с ревю кода по диффу как точкой контроля.
13. Проверьте персистентность: злодей возвращается
Полный вектор «устранение» включает вычистку мест, где бэкдор пересоздаёт себя:
# SSH-ключи: чужие authorized_keys
sudo find /root /home -name authorized_keys -exec ls -la {} \; -exec cat {} \;
# Пользователи с uid=0 (скрытый root) и свежие учётки
awk -F: '($3==0){print "uid0:", $1}' /etc/passwd
# Хуки инициализации, которые гонят payload при логине
grep -RInE "rc.local|profile.d|bashrc" /etc | grep -iE "curl|wget|base64|nc |ncat|/dev/tcp"
# Подозрительные setuid-бинарники (классический priv-esc-сувенир)
find / -perm -4000 -type f 2>/dev/null | sort > setuid-now.txt
debsums -c (Debian/Ubuntu) / rpm -Va (RHEL-семейство) сверяют установленные пакеты с эталонными хешами — если пакетный менеджер сам себя не обманывает, изменённые системные бинарники выплывают здесь. Это перекликается с AIDE/IMA из продвинутой защиты хоста.
Часть VI. Устранение и восстановление
14. «Вылечить» или «пересобрать» — честный выбор
| Лечить (точечно убрать) | Пересобрать (чистый образ) |
|---|---|
| Одна webshell, вектор понятен, персистентности нет | Подтверждённый рут / изменённые системные бинарники |
| SEO-спам в контенте/таблицах, исходники чисты | Невозможно доверять метатайму и «чистым» файлам |
Подменённый .htaccess с восстановимым оригиналом | Скрытый cron/authorized_keys, который вы не можете найти |
Правило: при сомнении в целостности ОС — пересобирайте. «Вылеченный» рутованный сервер остаётся рутованным: вы не можете быть уверены, что нашли все бэкдоры. Чистый пересбор + восстановление данных из проверенной копии — это единственный способ доказать себе чистоту, и именно поэтому он так часто быстрее, чем бессонная охота за бэкдорами.
15. Восстановление из бэкапа: копия обязана быть чище инцидента
Слепо развернуть бэкап — значит, возможно, развернуть и вебшелл (если инцидент начался раньше копии). Отсюда жёсткие проверки до отката:
# Целостность архива до разворачивания
gzip -t webroot-backup-2026-10-08.tar.gz
# Проверить «самый старый из подозреваемых» против копии: в копии нет IoC?
tar -tzf webroot-backup-2026-10-08.tar.gz | grep -F "wp-content/uploads/x.php" && echo "ВНИМАНИЕ: вебшелл уже в копии!"
# Дамп БД: проверить, что он из времени ДО атаки
grep -E "CREATE DATABASE|Dump completed" db-backup-2026-10-08.sql | head
Если в бэкапе тот же вектор — вся ветка «восстановление из копии» непригодна, откатывайтесь к снимку старше и заново считайте точку компрометации. Стратегия, когда и как делать копии, которые вообще переживут инцидент, — в руководстве по резервному копированию.
16. Ротация ВСЕХ секретов и патч ДО повторного подключения
Когда чистая площадка поднялась, до открытия трафика:
- Смена паролей: админка CMS, СУБД-пользователи, SSH (лучше переход на ключи + MFA), хостинг-панель, DNS-регистратора (управление DNS — перехват домена это отдельный вектор).
- Отзыв и перевыпуск токенов: API-ключи (защита API), OAuth-секреты, session-соли, ключи шифрования. Секреты из утечки больше не секреты.
- SSL: если есть подозрение на подмену — перевыпуск сертификатов и закрытие доступа к ключам (руководство по SSL).
- Патч корневой уязвимости: обновление плагинов/ядра, фикс кода из SQLi/XSS-практики, включение WAF (ModSecurity) как временный щит.
- Только после этого — снятие изоляции и возврат трафика, с включённым мониторингом на максимум чувствительности (Prometheus+Grafana): вы ожидаете «возвращение хозяина».
17. Финальная проверка «чисто ли»
Перед празднованием — пересканируйте: find -newermt снова пусто по IoC-окну, setuid/cron/authorized_keys совпадают с эталоном, исходящих соединений к пулам/IRC нет (ss -tunap чист), тестовые запросы к найденным векторам отдают 404. Это тот же набор, что вы вели для улик — теперь как приёмочный критерий.
Часть VII. Коммуникация: черные списки, партнёры, регулятор
18. Снять с «небезопасного» статуса в поиске
Сайт, раздающий малварь или фишинг, быстро попадает в блокировки браузера и поиск. Порядок разблокировки:
# Проверяете статус сами (подставьте свой сайт вместо example.test)
# Google Safe Browsing:
# https://transparencyreport.google.com/safe-browsing/search?url=example.test
# В Google Search Console: раздел «Проблемы безопасности» → Request Review
# В Яндекс Вебмастере: «Безопасность и нарушение прав» → снять жалобу после чистки
Review подают после устранения и восстановления, не «на авось»: поисковая система проверяет, что причина (спам-редирект, малварь) действительно убрана. В заявке кратко опишите вектор и что сделано — это ускоряет ручную проверку.
19. Юридический контур: когда вы обязаны сказать
Если скомпрометированы персональные данные, «чистка» не закрывает обязательства. Ориентиры (не юридическая консультация; сроки и форму сверяйте с актуальной редакцией права вашей юрисдикции):
- GDPR (ЕС/EEA и все, кто обрабатывает их данные): уведомление регулятора по утечке ПДн — ориентир не позднее 72 часов после подтверждения инцидента; при высоком риске для субъектов — уведомление и самих пользователей (ст. 33–34 GDPR).
- 152-ФЗ (РФ): об инциденте с персональными данными информируют Роскомнадзор в порядке и сроки по актуальной редакции и методичкам регулятора; зафиксируйте, какие данные и чьи затронуты.
- Отраслевые схемы (PCI DSS и т.п.): отдельные регламенты и сроки для платёжных данных.
- Партнёры и пользователи: статус-страница и честное коммюнике лучше, чем молчание и «мы ничего не знаем» в тикетах.
Вывод: контактный список и шаблон коммюнике готовятся на стадии подготовки (Часть I), а не в первые часы паники.
Часть VIII. Постмортем и профилактика: чтобы это было в последний раз
20. Разбор без обвинений (blameless)
Когда прод снова живой, соберите таймлайн инцидента и ответьте письменно:
- Где мы узнали об атаке (какой алерт сработал / что заметили руками)? Это точка MTTD — сравнивайте с тем, что должно было быть по детектированию.
- Почему превенция пропустила: уязвимый плагин, слабый пароль, незакрытый вход — и к какому пункту OWASP это относится.
- Где мы потеряли время: не было бэкапа? не сохранили volatile? ссорились о выключении?
- Что конкретно меняется: апдейт-политика, обязательный WAF, неизменяемые логи, MFA, тест восстановления бэкапа.
21. Превратить постмортем в чек-лист
Каждый пункт «что меняется» закрывается задачей с дедлайном и ответственным, а не намерением. Формально — это снова аудит безопасности только теперь с известным вектором: повторите соответствующую ему проверку из чек-листа и убедитесь, что дыра закрыта.
Инструмент под задачу
Отследить «когда началось и откуда» — по web-логу и syslog: анализатор покажет паттерны запросов, подозрительные IP и аномальные строки, с которых начался инцидент. Попробуйте инструмент прямо здесь, на своих данных:
Результат анализа:
Чек-лист реагирования (шпаргалка на первые 2 часа)
- Не удалять подозрительное. Зафиксировать «сейчас» в UTC, проверить NTP.
- Снять volatile: `ss -tunap`, `ps auxwwf`, список соединений и процессов → `/evidence`.
- Объявить уровень триажа: webshell / частичный / рутовый — от него зависит «лечить vs пересобрать».
- Снять образы: БД (`mysqldump`), веб-корень, `/etc`; `sha256sum` → `SHA256SUMS.txt`.
- Изолировать: бан IP / 503 для площадки / DROP исходящих — оставив SSH-белый список.
- Построить таймлайн: `find -newermt` + `grep` вектора в access-log + аутентификация.
- Проверить персистентность: cron, таймеры, `authorized_keys`, uid=0, setuid, `debsums -c`.
- Восстановиться: чистый образ или бэкап *чище точки компрометации* (`gzip -t`, проверка на IoC).
- Ротация ВСЕХ секретов + патч уязвимости → только потом возврат трафика.
- Снять блокировки (Safe Browsing / Search Console / Вебмастер) после чистки.
- Оценить обязательства по уведомлению (GDPR/152-ФЗ/PCI) и связаться с регулятором/пользователями.
- Написать постмортем и превратить его в задачи с дедлайнами.
Методология — по NIST SP 800-61 (Computer Security Incident Handling Guide) и OWASP Incident Response Cheat Sheet. Команды и пути логов рассчитаны на типичный Linux-хост с LEMP; конкретные пути к access/error-логам зависят от вашей конфигурации Nginx/Apache. Материал носит образовательно-практический характер и не является юридической консультацией по срокам и формату уведомления регулятора.
👤 Зарегистрируйтесь, чтобы добавить материал в закладки.
