MAATRIX / Блог / Скомпрометирован или просто глючит: как отличить взлом от кривого обновления

Скомпрометирован или просто глючит: как отличить взлом от кривого обновления

MAATRIX

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

Почему симптомы одинаковые, а причины — разные

Взлом и неудачное обновление на первый взгляд выглядят одинаково, потому что оба меняют поведение системы без явного предупреждения. Процесс ест память, которую раньше не ел. Сервис перезапускается сам по себе. В логе приложения — новые строки с ошибками. Сайт отдаёт 502 там, где вчера всё работало. Ни один из этих симптомов сам по себе не говорит, взлом это или нет — он говорит только «что-то изменилось», а вот что именно, нужно устанавливать отдельно.

Разница между двумя сценариями — не в симптомах, а в источнике изменения:

  • Обновление, деплой, изменение конфига — событие, которое кто-то из команды инициировал сам, оно есть в истории пакетного менеджера, в логе CI/CD, в git-истории конфигурации. У него есть автор, время и, как правило, обратимость: откатить пакет или деплой можно за минуты.
  • Компрометация — событие, которое инициировал кто-то посторонний, и оно почти никогда не оставляет запись в ваших легитимных источниках истории. Зато оставляет артефакты другого рода: файлы, процессы, учётные записи, которые не появляются сами по себе в ходе штатной работы системы.

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

Признаки, которые почти всегда указывают на взлом

Компрометация системы почти всегда оставляет артефакты — что-то, чего не было и что не появляется в результате штатных операций обновления или деплоя. Ключевое слово здесь — «новое и необъяснённое»: не просто незнакомый процесс (мало ли что вы забыли, как называется системная служба), а процесс, файл или учётная запись, для которых нет ни одной легитимной причины появления.

Незнакомые процессы и бинарники.

ps auxf
ss -tulnp

Ищите процессы с именами, маскирующимися под системные (kworker, но с лишним пробелом или в нетипичном пути), процессы, запущенные из /tmp, /var/tmp, /dev/shm — легитимный софт из временных каталогов почти никогда не работает постоянно. Отдельно смотрите на процессы, слушающие порты, которых не должно быть ни в одном известном сервисе.

Новые пользователи и SSH-ключи.

awk -F: '$3 >= 1000 {print $1, $3, $6}' /etc/passwd
cat /etc/passwd | grep -E ':0:0:'
for u in $(cut -f1 -d: /etc/passwd); do
  echo "== $u =="; sudo cat "$(eval echo ~$u)/.ssh/authorized_keys" 2>/dev/null
done

Любой пользователь с UID 0, кроме root, — почти всегда компрометация. Новый обычный пользователь, которого никто из команды не заводил, или лишняя строка в authorized_keys — то же самое: ни обновление пакета, ни деплой приложения таких артефактов не создают.

Задачи cron и systemd-таймеры, которые никто не ставил.

for u in $(cut -f1 -d: /etc/passwd); do crontab -u "$u" -l 2>/dev/null; done
systemctl list-timers --all
cat /etc/cron.d/* 2>/dev/null

Легитимные задачи появляются вместе с установкой конкретного пакета или явным действием администратора — если задача не привязана ни к одному известному сервису и запускает что-то похожее на скрипт из одной строки с curl/wget и пайпом в shell, это серьёзный повод для тревоги.

Изменённые системные бинарники. Пакетные менеджеры умеют сверять контрольные суммы установленных файлов с эталоном из репозитория:

# Debian/Ubuntu (нужен пакет debsums)
sudo debsums -c

# AlmaLinux/RHEL/CentOS
sudo rpm -Va --nomtime | grep '^..5'

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

Разрывы и подчистки в логах. Если в journalctl или auth.log есть подозрительный провал во времени — сервис писал события, резко замолчал на несколько часов, потом снова начал писать как ни в чём не бывало, — это может быть чисткой следов. Такое встречается и при сбоях ротации логов, поэтому разрыв — повод проверить внимательнее, а не окончательный вердикт.

Исходящий трафик на незнакомые адреса. ss -tnp или lsof -i покажут установленные соединения; сверьте внешние IP с тем, что вообще должно ходить наружу. Постоянное соединение на незнакомый адрес от процесса, который в принципе не должен иметь сетевой активности, — заметный сигнал.

Общая логика всех этих пунктов одна: артефакт есть, а объяснения в собственных источниках информации — нет.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Признаки, которые почти всегда объясняются своим изменением

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

Обновление пакетов сменило поведение по умолчанию. Мажорное обновление веб-сервера, интерпретатора или библиотеки нередко меняет дефолтные значения конфига, формат опций или строгость проверок — то, что вчера прощалось, сегодня валит запуск с ошибкой. Это не баг в вашем коде и не взлом — это ожидаемая (хоть и неприятная) часть апгрейда, и подробнее о том, почему обновления действительно иногда ломают больше, чем чинят, а иногда — совсем наоборот, разобрано в статье про миф о вреде обновлений.

Конфликт зависимостей после апгрейда. Один пакет подтянул новую версию общей библиотеки, из-за чего у другого изменилось поведение — классика для систем с ручной установкой пакетов (pip, npm, gem) вперемешку с системными.

Автообновления безопасности сработали ночью. Если на сервере включены unattended-upgrades (Debian/Ubuntu) или аналог на RHEL-системах, часть перезапусков служб и случайных даунтаймов объясняется штатным обновлением, а не вмешательством — стоит проверить это в первую очередь.

Деплой принёс новый конфиг или переменную окружения. Если приложение деплоится через CI/CD, изменение поведения может быть следствием последнего пайплайна — новая переменная окружения, изменённый конфиг, обновлённая зависимость в package.json/requirements.txt.

Ротация или переполнение диска логами. Рост нагрузки, зависания записи, ошибки «no space left on device» — частый эффект от логов, разросшихся из-за трафика или debug-режима, оставленного после отладки, а не вмешательства.

Истёкший сертификат или изменившийся DNS. Ошибки на уровне TLS или недоступность по имени часто выглядят пугающе, но объясняются рутинным жизненным циклом сертификата или записи, а не атакой.

Признак этой категории тот же, что и для взлома, только с обратным знаком: у изменения есть автор, время и запись в одном из ваших собственных легитимных источников — истории пакетов, git-логе конфигурации, логе деплоя.

Порядок диагностики: сначала свои изменения, потом чужие следы

Правильная последовательность экономит часы: сначала закрыть максимально вероятную и проверяемую гипотезу (легитимное изменение), и только если она не объясняет симптом — переходить к поиску следов вмешательства.

Шаг 1. Поднять историю обновлений пакетов.

# Debian/Ubuntu
grep -E '^(Start-Date|Commandline|Upgrade|Install|Remove)' /var/log/apt/history.log
zgrep -h -E '^(Start-Date|Commandline)' /var/log/apt/history.log.*.gz

# AlmaLinux/RHEL/CentOS
dnf history list
dnf history info <ID>

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

Шаг 2. Поднять историю деплоев и изменений конфигурации. Если конфиги под git — git log --since="7 days ago" -- /etc/nginx/ (или соответствующий путь) сразу покажет, что и когда менялось и кем. Логи CI/CD дадут то же самое для кода приложения.

Шаг 3. Проверить время последнего перезапуска служб и системы.

uptime -s
systemctl status <service> | grep Active
journalctl -u <service> --since "3 hours ago"
who -b
last reboot | head

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

Шаг 4. Только теперь — искать признаки постороннего. Если шаги 1–3 не дали объяснения (обновлений не было, деплоя не было, перезапуск не по расписанию), переходите к проверкам из предыдущего раздела: пользователи, ключи, cron, контрольные суммы бинарников, сетевые соединения.

Шаг 5. Сверить временные метки артефакта с временными метками легитимных изменений.

find / -mtime -3 -type f 2>/dev/null | grep -vE '^/(proc|sys|run)'
stat /путь/к/подозрительному/файлу

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

Такой порядок экономит ресурс на панику: проверка пакетного менеджера и git-лога занимает пять минут, а полноценное расследование с фиксацией улик, изоляцией сервера и переустановкой — часы и дни. Алгоритм действий на случай, если компрометация всё же подтвердилась, — в статье «Взломали сервер: пошаговый план» и в плане реагирования на инцидент.

Сводная таблица: на что смотреть в первую очередь

СимптомВероятная легитимная причинаКогда стоит насторожиться
Сервис не стартует после перезагрузкиОбновление изменило дефолтный конфиг или синтаксисКонфиг не менялся, обновлений не было, а сервис всё равно не стартует
Высокая загрузка CPU неизвестным процессомФоновая индексация, пересборка кэша, антивирус/бэкап по расписаниюПроцесс не соответствует ни одному установленному пакету, путь к бинарнику — /tmp или /dev/shm
Новая запись в /etc/passwdПлановое создание учётки администратором или системой управления конфигурациейНикто из команды не подтверждает создание, UID 0 у не-root пользователя
Незнакомый слушающий портНовый сервис только что задеплоен и ещё не задокументированПорт не привязан ни к одному процессу из systemctl list-units, открыт давно
Рост исходящего трафикаСинхронизация бэкапов, обновление кэша CDN, всплеск легитимного трафикаСоединения идут на IP, не связанный ни с одним известным интеграционным партнёром
Ошибки TLS/сертификатаИстёк или не продлился автоматически сертификатСертификат в порядке, ошибка появляется точечно у части клиентов
Пропажа строк в логеРотация логов сработала раньше срока из-за объёмаРазрыв точно совпадает с окном подозрительной активности, ротация по логам ротации не подтверждается

Таблица не заменяет проверку — она задаёт направление: для каждого симптома есть более вероятная скучная причина, и её стоит исключить первой.

Как не свалиться в паранойю на пустом месте

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

Ведите собственный журнал изменений. Простой файл или канал, куда падает запись о каждом обновлении, деплое и ручном изменении конфига, за секунды закрывает большинство вопросов «что это вообще такое» — без него приходится реконструировать историю по обрывочным логам.

Не переустанавливайте систему при первой находке. Переустановка с нуля — правильный ответ на подтверждённую компрометацию, но не на любую странность. Если артефакт объясняется шагами 1–3 из порядка диагностики выше, откат обновления или деплоя обычно быстрее и дешевле пересборки сервера.

Разделяйте «не могу объяснить» и «точно взлом». Отсутствие сразу найденного объяснения — не доказательство компрометации, а сигнал копать глубже по тем же легитимным источникам: возможно, изменение внёс коллега, о котором вы не знали.

Держите базовый уровень «нормального». Если вы не знаете, сколько процессов и какие порты обычно открыты на чистом сервере, любая находка будет казаться подозрительной. Периодический снимок ss -tlnp и списка пакетов, сохранённый как эталон, экономит нервы при следующей проверке — та же логика полезна для регулярного аудита логов сервера, который помогает заметить отклонение до того, как оно станет инцидентом.

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

Паранойя и беспечность — две стороны одной ошибки: обе означают решение без проверки конкретных фактов. Порядок диагностики выше существует именно для того, чтобы факт был отделён от тревоги.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

С чего начать, если сервер ведёт себя странно прямо сейчас?

С истории обновлений пакетов и деплоев за последние сутки-двое — grep по /var/log/apt/history.log или dnf history list, плюс git-лог конфигурации, если она версионируется. В большинстве случаев ответ находится уже на этом шаге.

Обновление точно ни при чём — что дальше?

Переходите к поиску артефактов: новые пользователи и SSH-ключи, незнакомые процессы и слушающие порты, изменённые системные бинарники (debsums -c или rpm -Va), задачи cron, которые никто не ставил.

Можно ли доверять логам, если подозреваешь компрометацию?

Частично. Атакующий с root-доступом способен подчистить auth.log и bash_history. Разрыв или чистая пустота там, где должна быть активность, — сам по себе сигнал, но лучше опираться и на источники, которые сложнее подделать: снимки процессов, сохранённые за пределами сервера, внешний мониторинг.

Что делать, если не уверены на 100%, взлом это или баг?

Действовать по худшему сценарию для критичных систем: изолировать от сети (не выключая), зафиксировать текущее состояние процессов и соединений в файл, скопировать его за пределы сервера, и уже после этого продолжать разбираться — так вы не теряете улики, даже если окажется, что дело было в обновлении.

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

Если найден хотя бы один артефакт без легитимного объяснения (чужой SSH-ключ, пользователь с UID 0, изменённый системный бинарник) — да, переустановка обоснована. Если все находки объясняются шагами диагностики выше — обычно достаточно отката обновления или деплоя.

Как долго обычно занимает такая проверка?

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

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →