MAATRIX / Блог / Сервер взломали через забытый порт: реконструкция по логам

Сервер взломали через забытый порт: реконструкция по логам

MAATRIX

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

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

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

Типичные поводы насторожиться:

  • сервер стал медленнее без видимой причины — процессор или память забирает процесс с непонятным именем;
  • провайдер прислал уведомление об аномальном исходящем трафике или жалобе на спам/сканирование с вашего IP;
  • в last или who видна сессия в то время, когда с сервером никто из команды не работал;
  • в ~/.ssh/authorized_keys обнаружился ключ, который никто не добавлял;
  • появился новый системный пользователь или пользователь с UID 0, которого не заводили;
  • мониторинг диска показывает рост непонятного каталога — иногда там лежат инструменты атакующего;
  • антивирус или rkhunter/chkrootkit, запущенный по другому поводу, случайно находит постороннее.

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

Реконструкция вектора атаки: порт, который забыли закрыть

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

Дальше время работает против такого сервиса сразу по двум направлениям:

  1. Софт не обновляется. Никто не следит за версией того, что и так «временное», — патчи безопасности проходят мимо, а уязвимость, найденная исследователями через полгода-год, остаётся актуальной именно для этого экземпляра.
  2. Конфигурация остаётся дефолтной. Тестовые сервисы поднимают быстро, часто с паролем или токеном «из коробки», без TLS, иногда вовсе без аутентификации — «это же только для отладки, потом закрою».

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

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

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

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

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

Как восстановить картину по логам задним числом

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

История правил фаервола. Если использовался ufw, полезно посмотреть на изменения конфигурации:

# когда менялись правила ufw
sudo ls -la /etc/ufw/
sudo cat /var/log/ufw.log | grep -i 'RULE'

Для iptables без отдельного логирования изменений придётся полагаться на бэкапы конфигурации (если они делались через iptables-save в cron) или на историю команд — см. ниже про sudo. Если в инфраструктуре есть система управления конфигурацией (Ansible, Puppet, Chef) — это лучший источник: там обычно виден коммит, который добавил правило «временно» и который так и не был отменён.

auth.log / secure log. Это основной источник по попыткам и фактам входа:

# Debian/Ubuntu
sudo zgrep -h "Accepted\|Failed" /var/log/auth.log* | less

# RHEL/AlmaLinux/CentOS
sudo zgrep -h "Accepted\|Failed" /var/log/secure* | less

Смотрите не только на успешные входы (Accepted), но и на последовательность Failed password перед ними — резкий пул неудачных попыток с одного IP, а затем внезапный успех, часто выдаёт подбор пароля или использование утёкших учётных данных. Обратите внимание на время: если успешный вход случился в момент, когда никто из команды объективно не мог сидеть за сервером — это сильный маркер.

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

sudo grep sudo /var/log/auth.log*
sudo journalctl _COMM=sudo --since "30 days ago"

Если у скомпрометированного пользователя была история команд (~/.bash_history, ~/.zsh_history), стоит проверить и её — но с поправкой на то, что опытный атакующий часто чистит или отключает историю, поэтому её отсутствие само по себе тоже информативно.

Снимок открытых портов и процессов на момент инцидента. Если на сервере стоял мониторинг (Zabbix, Prometheus node_exporter, простой cron с логированием ss -tlnp раз в час), это золотая жила — можно увидеть, когда именно появился лишний слушающий порт. Если такого мониторинга не было, единственный шанс — актуальный снимок уже после обнаружения:

ss -tlnp
ss -tunp

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

Логи самого временного сервиса. Если это был веб-сервер, у него, скорее всего, есть собственный access/error лог — там может быть виден момент первого подозрительного запроса, характерный User-Agent сканера или паттерн, похожий на попытку эксплуатации известной уязвимости.

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

Что злоумышленник обычно делает дальше

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

Закрепление (persistence). Первая цель — не потерять доступ, даже если дыру, через которую зашли, закроют. Отсюда:

  • добавление своего ключа в ~/.ssh/authorized_keys существующего или нового пользователя;
  • создание нового системного или обычного пользователя, иногда с именем, похожим на легитимное (sysadmin, backup, www-data2);
  • задачи в cron или systemd-таймеры, которые периодически восстанавливают доступ, даже если что-то удалить вручную;
  • модификация скриптов автозапуска (rc.local, systemd unit-файлы) для запуска стороннего процесса при перезагрузке.

Эскалация привилегий. Если начальный доступ получен от имени непривилегированного сервиса или пользователя, следующий шаг — попытка добраться до root: поиск уязвимостей в установленном ПО, проверка неправильно настроенных прав sudo, эксплуатация известных локальных уязвимостей повышения привилегий (LPE) в ядре или системных утилитах.

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

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

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

Немедленные действия при обнаружении компрометации

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

1. Изолировать сервер от сети, не выключая его. Полное выключение стирает состояние оперативной памяти и завершает активные процессы, которые могли бы многое рассказать. Правильнее ограничить сеть фаерволом, оставив доступ только со своего IP:

ufw default deny incoming
ufw default deny outgoing
ufw allow from ВАШ_IP to any port 22 proto tcp
ufw enable

Если панель провайдера позволяет изолировать сервер на уровне сети (отдельный VLAN, блокировка на уровне гипервизора) — это ещё надёжнее, потому что не зависит от того, скомпрометирован ли сам фаервол на сервере.

2. Не удалять улики сразу. Желание немедленно снести подозрительный процесс, файл или пользователя понятно, но до того как зафиксированы состояния — списки процессов, сетевых соединений, файлов с недавним временем изменения — лучше воздержаться:

ps auxf > /root/incident_ps.txt
ss -tulnp > /root/incident_ss.txt
find / -mtime -14 -type f 2>/dev/null > /root/incident_recent_files.txt

Эти снимки стоит сразу скопировать за пределы сервера (на другую машину или в облако), потому что если атакующий ещё имеет доступ, он может успеть их подчистить.

3. Сменить все ключи и пароли — везде, а не только на скомпрометированном сервере. Если с этого сервера были доступны другие системы (по SSH-ключу, сохранённому токену, паролю, который где-то совпадает), считайте скомпрометированными и их тоже: SSH-ключи, пароли пользователей, токены API, доступы к базам данных, интеграции с внешними сервисами.

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

Профилактика: чтобы забытый порт не повторился

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

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

ss -tlnp
ss -tulnp

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

Правило «закрывать за собой». Технически самое простое, но организационно самое сложное правило: если сервис поднят для теста или отладки — при завершении работы явно закрыть порт в фаерволе и остановить/удалить сам сервис, а не полагаться на то, что «он и так никому не мешает». Практический способ дисциплинировать это — заводить временные правила фаервола с явным сроком жизни (например, отдельным cron-заданием, которое снимает правило через N дней) или просто вести список «что открыто и зачем» рядом с конфигурацией сервера.

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

ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 443/tcp

Мониторинг изменений сетевой конфигурации. Даже простой cron, который раз в час пишет вывод ss -tlnp в лог с ротацией, задним числом превращается в бесценный источник для расследования — вы не гадаете, когда появился порт, а видите это по времени. О том, как в принципе организовать поиск открытых портов и закрыть лишнее, подробно разобрано в статье про открытые порты на сервере, а пошаговый план на случай, если компрометация уже подтверждена, — в материале «Взломали сервер: пошаговый план».

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

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

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

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

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

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

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

Как понять, что забытый порт вообще существует, если его никто не документировал?

Начните с ss -tlnp и сверьте список с тем, что реально должно быть открыто. Для каждого незнакомого порта проверьте процесс (lsof -i :ПОРТ) и время его запуска — если он живёт месяцами и никто не объясняет зачем, это кандидат на закрытие.

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

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

Обязательно ли переустанавливать систему полностью, если нашли только один посторонний процесс?

Гарантированного «частичного» решения не существует: раз система была скомпрометирована, надёжна только переустановка с нуля. Чистка одного процесса снижает риск, но не даёт уверенности, что это единственная точка закрепления.

Сколько времени обычно занимает такое расследование?

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

Стоит ли сообщать о взломе провайдеру сервера?

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

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

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

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