Сервер достался по наследству: проверка чужой машины перед боем
Вы купили бизнес вместе с его инфраструктурой, сменили подрядчика или просто вышли на новую работу — и получили доступ к серверу, который настраивал кто-то другой, часто годы назад. У вас есть root, но нет ни малейшего представления, что на этой машине реально происходит: кто ещё туда заходит, что запускается по расписанию, какие дыры оставлены намеренно или по забывчивости. Довериться такому серверу с ходу — плохая идея, даже если он «просто работает». Ниже — практический порядок проверки, который займёт от пары часов до дня в зависимости от масштаба, и после которого вы будете понимать систему, а не гадать.
Содержание
Сначала — снимите слепок системы, не полагаясь на неё
Первое правило: не верьте выводам команд на этой машине больше, чем должны. Если сервер скомпрометирован по-настоящему серьёзно (руткит с подменой ls, ps, netstat), локальные утилиты могут врать. Для рядового случая «доставшийся по наследству сервер» это редкость — обычно проблема не в руткитах, а в забытых доступах и незакрытых дырах. Но привычку стоит взять сразу: критичные проверки дублируйте внешними средствами — сканом портов снаружи, а не только ss изнутри.
Прежде чем что-либо менять, зафиксируйте состояние на момент приёмки — это ваша точка отсчёта и заодно защита самого себя: если через месяц что-то отвалится, вы будете знать, было это так изначально или сломали вы.
mkdir -p ~/server-audit-$(date +%Y%m%d)
cd ~/server-audit-$(date +%Y%m%d)
# пользователи и группы
getent passwd > passwd.txt
getent group > group.txt
# все ключи и cron
find / -name authorized_keys 2>/dev/null -exec cat {} \; > all_authorized_keys.txt
crontab -l > root_crontab.txt 2>&1
for u in $(cut -f1 -d: /etc/passwd); do echo "== $u =="; crontab -u $u -l 2>/dev/null; done > all_crontabs.txt
# слушающие порты и процессы
ss -tulnp > listening_ports.txt
ps auxf > processes.txt
# установленные пакеты
dpkg -l > packages.txt 2>/dev/null || rpm -qa > packages.txt
# systemd юниты
systemctl list-unit-files --state=enabled > enabled_units.txt
systemctl list-timers --all > timers.txt
Это займёт пять минут и даст материал для сравнения на каждом следующем шаге. Если ситуация похожа на конфликтную передачу дел (администратор ушёл, не оставив документации, или доступ отзывался в спешке), сначала прочитайте план возврата контроля, когда единственный админ ушёл со всеми паролями — там разобран смежный сценарий с юридической и организационной стороны, здесь — только техническая проверка машины.
Пользователи, группы и права доступа
Сверьте passwd.txt с реальным списком людей, у которых должен быть доступ — обычно это команда из двух-трёх строк в почте или в HR-системе, а не документ. Всё, что не совпадает, требует объяснения.
Смотрите не только на список UID, но и на детали:
# пользователи с UID 0 (кроме root — тревога)
awk -F: '$3 == 0 {print $1}' /etc/passwd
# пользователи с login shell (могут реально зайти)
awk -F: '$7 !~ /(nologin|false)$/ {print $1, $7}' /etc/passwd
# кто состоит в sudo/wheel
getent group sudo wheel 2>/dev/null
# файл sudoers на самодельные правила
cat /etc/sudoers
ls -la /etc/sudoers.d/
cat /etc/sudoers.d/*
Особое внимание — на NOPASSWD:ALL в /etc/sudoers.d/: часто это оставляют «для удобства» деплой-скрипта и забывают, а по факту это равносильно раздаче root без пароля любому, кто получит доступ к этому аккаунту. Отдельно проверьте домашние каталоги на пользователей без записи в /etc/passwd — иногда учётку удаляют, а /home/имя остаётся с чужими ключами и историей команд:
ls /home/
# сверьте каждую папку с выводом getent passwd
Если находите техническую учётку подрядчика, которую давно пора было отключить — это типовая ситуация, разобранная в статье про аудит authorized_keys подрядчика за час: там показано, как быстро понять, кто и когда этим ключом пользовался, прежде чем его отзывать.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверSSH-ключи, пароли и все секреты — меняем всё
Это самый важный пункт, потому что именно он определяет, кто ещё, кроме вас, может зайти на сервер прямо сейчас. Правило простое: если вы не выдавали доступ лично — считайте, что он скомпрометирован, и меняйте.
Проверьте authorized_keys у каждого пользователя, не только у root:
find / -name authorized_keys -exec ls -la {} \; 2>/dev/null
find / -name authorized_keys -exec cat {} \; 2>/dev/null
Каждая строка — это чей-то ключ. Комментарий в конце строки (user@hostname) часто подсказывает, кому ключ принадлежал, но доверять ему нельзя — комментарий может быть любым текстом. Если список большой и непонятно, кто есть кто, проще всего перевыпустить доступ с нуля:
# бэкап на всякий случай
cp /root/.ssh/authorized_keys /root/.ssh/authorized_keys.old-$(date +%Y%m%d)
# очистить и вписать только свой ключ
echo "ssh-ed25519 AAAA...ваш-реальный-ключ... you@newlaptop" > /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
Дальше по списку — всё, что могло быть известно прежней команде:
- Пароли всех системных пользователей —
passwd username, включая учётки сервисов, если у них вообще были пароли (в идеале не должно быть, только ключи). - root-пароль — даже если вход по паролю для root отключён (
PermitRootLogin noвsshd_config), сам пароль стоит сменить: он может использоваться дляsu, консоли провайдера или KVM. - API-ключи и токены — в
.env,~/.aws/credentials,~/.config, переменных окружения systemd-юнитов, секретах Docker/Kubernetes. Проверьтеgrep -riE "api[_-]?key|secret|token|password" /etc/environment /etc/systemd/system/*.service.d/*.conf 2>/dev/null. - Ключи баз данных и панелей управления — пароль root MySQL/PostgreSQL, логин панели хостинга, если она стоит на сервере.
- SSH host key сервера, если есть подозрение на серьёзную компрометацию, а не просто на утечку доступа — при пересоздании клиенты получат предупреждение о смене отпечатка, это нормально в контексте смены владельца.
Заодно проверьте sshd_config на явные ослабления, которые могли остаться от прежней команды «для удобства»:
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
X11Forwarding no
AllowTcpForwarding no
Если PasswordAuthentication всё ещё yes — это первое, что нужно закрыть. После смены конфигурации — systemctl restart sshd и обязательно проверьте новое подключение в отдельной сессии, не закрывая текущую, чтобы не остаться без доступа.
Cron, systemd и автозагрузка: ищем чужие задачи
Расписанные задачи — самое частое место, где остаётся что-то, о чём никто не помнит: от безобидного скрипта ротации логов до канала связи, который прежний администратор оставил себе «на всякий случай». Проверять нужно не только crontab -l, а все возможные места.
# crontab каждого пользователя
for u in $(cut -f1 -d: /etc/passwd); do
echo "=== $u ==="
crontab -u $u -l 2>/dev/null
done
# системные cron-каталоги
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ /etc/cron.weekly/ /etc/cron.monthly/
# анакрон, если есть
cat /etc/anacrontab 2>/dev/null
Отдельно — systemd-таймеры, которые всё чаще заменяют cron и про которые забывают проверить именно поэтому:
systemctl list-timers --all
systemctl list-unit-files --state=enabled | grep -v '@'
Каждый включённый юнит стоит открыть и посмотреть, что он реально запускает (systemctl cat имя.service), особенно если название ни о чём не говорит или явно нестандартное. Подробнее о том, где ещё прячутся забытые задачи кроме самого crontab, — в статье чужая задача в cron: где ещё смотреть кроме crontab.
Что должно насторожить в выводе:
- задача от имени пользователя, который не должен был иметь shell-доступ;
- команда с
curl/wgetна внешний адрес без очевидной связи с рабочими процессами; - запуск через
base64 -dили явно обфусцированная строка; - задача, добавленная позже, чем должна была появиться (проверьте время модификации файлов crontab через
stat).
Сеть: открытые порты и правила фаервола
Сравните, что сервер слушает изнутри, с тем, что реально доступно снаружи — это не всегда одно и то же, если проброс идёт через docker или NAT-правила, которые в упор не видны в стандартном выводе ufw status.
# изнутри — кто слушает
ss -tulnp
# правила фаервола
ufw status verbose 2>/dev/null || iptables -L -n -v
iptables -t nat -L -n -v
# docker может пробивать firewall своими правилами — проверьте отдельно
iptables -t nat -L DOCKER -n -v 2>/dev/null
Изнутри картина может врать в лучшую сторону — например, правило ufw формально стоит, но docker добавил свою цепочку NAT в обход. Поэтому обязательно проверьте снаружи, со своей машины или внешнего сканера:
nmap -Pn -p- ваш.ip.адрес.сервера
Полное сканирование всех 65535 портов займёт время, но именно оно покажет реальную картину, а не то, что сервер думает о себе сам. Каждый открытый порт должен быть объясним: вы должны понимать, какой сервис его слушает и зачем он вообще должен быть доступен извне, а не только с loopback. Подробный разбор методики — в статье как проверить и закрыть открытые порты на сервере.
Частые находки на «доставшихся по наследству» серверах: панель управления базой данных, забытая открытой на 8080/8081; Redis без пароля на дефолтном порту; старый инструмент мониторинга, который никто не поддерживает и не патчит уже пару лет. Каждый такой сервис — потенциальная точка входа, даже если сейчас через него ничего не произошло.
Версии ПО и базовые индикаторы компрометации
Устаревший софт — не сама угроза, а увеличенная площадь атаки: чем старее версия, тем больше публично известных проблем в ней потенциально закрыто в более новых релизах. Не нужно гнаться за конкретными номерами уязвимостей — их слишком много и они постоянно меняются, важнее общий принцип: если пакет не обновлялся год-два, это сигнал проверить его в первую очередь.
# сколько пакетов давно не обновлялось (Debian/Ubuntu)
apt list --upgradable 2>/dev/null | wc -l
# дата последнего apt update/upgrade
grep -E "upgrade|install" /var/log/apt/history.log | tail -20
# ядро — насколько отстаёт от актуального для дистрибутива
uname -r
cat /etc/os-release
Если дистрибутив старше двух актуальных LTS-релизов назад или вышел из официальной поддержки (ubuntu-support-status для Ubuntu) — это отдельный проект по миграции, а не строчка в чек-листе, но зафиксировать этот факт нужно сразу.
Дальше — базовый набор проверок на индикаторы компрометации. Это не полноценный форензик-анализ (для реального подозрения на взлом нужен отдельный процесс с сохранением образа диска), а быстрый скрининг, чтобы понять, стоит ли вообще доверять машине или проще поднять новую и перенести данные.
# неожиданные SUID-бинарники — частый способ закрепления
find / -perm -4000 -type f 2>/dev/null > suid_files.txt
# сравните с эталонным списком для вашего дистрибутива, необычные пути — тревога
# процессы, слушающие сеть, но с подозрительным путём к бинарнику
ls -la /proc/*/exe 2>/dev/null | grep -E "deleted|tmp"
# история команд root — если не чистили специально
cat /root/.bash_history
# последние изменённые файлы в системных каталогах
find /etc /usr/bin /usr/sbin -mtime -30 -type f 2>/dev/null
# кто и когда логинился
last -50
lastb -20 2>/dev/null
Для более системного прохода удобно использовать lynis — он проходит по десяткам пунктов и даёт отчёт с оценкой hardening, полезно как второе мнение поверх ручной проверки: apt install lynis && lynis audit system. Файл /proc/*/exe со статусом deleted у процесса, который слушает порт, — почти всегда повод остановиться и разобраться отдельно, а не двигаться дальше по чек-листу.
Если после всех проверок остаются сомнения — не полагайтесь на латание конкретной находки. Иногда быстрее и надёжнее поднять чистый сервер, перенести на него только данные и приложение (не конфиги и не системные файлы старой машины), чем до конца выяснять, насколько глубоко сидит проблема на унаследованной системе.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Сколько времени реально занимает такая проверка?
Для небольшого сервера с одним-двумя сервисами — три-четыре часа на все пункты, включая внешнее сканирование портов. Для инфраструктуры с десятком сервисов и историей в несколько лет — закладывайте день, особенно если находки требуют разбирательства, а не просто закрытия.
Обязательно ли переустанавливать сервер с нуля вместо аудита?
Нет, если чек-лист не выявил ничего похожего на активную компрометацию (обфусцированные cron-задачи, процессы с удалённым бинарником, неизвестные SUID-файлы). В большинстве случаев «наследство» — это забытые доступы и устаревший софт, а не действующий взлом, и это закрывается сменой ключей и паролей плюс обновлением.
Что делать, если прежний администратор недоступен и не может объяснить находку?
Считайте необъяснённое подозрительным по умолчанию: отключайте, изолируйте, только потом разбирайтесь. Если это была легитимная задача — она обнаружится через сообщения от заказчика или сбой сервиса, и её проще восстановить осознанно, чем оставить работать вслепую.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →