Что нового

Как я проверил безопасность двух VPS после инцидента с гипервизором: полный аудит Ubuntu, SSH и TLS

Изображение ChatGPT 29 окт. 2026 г., 23_38_32.jpg

​

Введение​


В октябре 2026 года я получил уведомление от своего VPS-провайдера об инциденте безопасности, связанном с инфраструктурой виртуализации.

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

На тот момент у меня работали два VPS с Ubuntu, обслуживавшие несколько веб-сервисов. После получения уведомления я решил провести самостоятельное расследование, проверить состояние операционных систем, заменить потенциально скомпрометированные ключи и сохранить материалы для последующего анализа.

В этой статье я подробно расскажу, как проводил проверку, какие инструменты использовал, что удалось обнаружить и какие меры защиты предпринял.

Рассмотрю не только базовый аудит SSH и системных журналов, но и:

  • проверку истории входов и активности пользователей;
  • поиск механизмов закрепления в Ubuntu;
  • анализ systemd, cron, PAM, SUID/SGID и Linux capabilities;
  • замену SSH host keys;
  • проверку ключей технической поддержки провайдера;
  • перевыпуск и отзыв сертификатов Let's Encrypt;
  • ротацию ACME-аккаунтов Certbot;
  • ограничение опасных RPC QEMU Guest Agent;
  • проверку nginx reverse proxy;
  • создание зашифрованных архивов доказательств;
  • проверку полученных архивов на Windows.

Важное замечание об обезличивании.

Все названия проектов, серверов, пользовательские IP-адреса, нестандартные порты, имена пользователей и другие идентифицирующие данные в статье заменены условными примерами.

Для доменов используются зарезервированные example.com и example.net, а для IP-адресов — специальные документационные диапазоны, например 192.0.2.0/24 и 198.51.100.0/24.

Имя operator и SSH-порт 22222 также являются вымышленными.

Все команды необходимо адаптировать к собственной инфраструктуре перед выполнением.

Содержание

Введение
1. Исходные данные и характер инцидента
   Какие серверы я проверял
2. Почему я не стал сразу переустанавливать VPS
3. Первичная проверка Ubuntu
   Неожиданный результат
4. Анализ SSH-подключений
   Проверка эффективной конфигурации SSH
5. Обнаружение ключа технической поддержки провайдера
   Сохранение ключа как доказательства
   Отключение ненужного ключа
6. Ротация SSH host keys
   Сохранение старых ключей
   Генерация новых ключей
   Проверка новых отпечатков
7. Исправление дублирующегося SSH-порта
8. Проверка сетевого доступа и UFW
9. Проверка QEMU Guest Agent
   Блокировка чувствительных RPC
10. Ротация сертификатов Let's Encrypt
    Проверка действующих сертификатов
    Создание нового ACME-аккаунта
    Перевыпуск с новыми приватными ключами
    Проверка TLS через OpenSSL
11. Отзыв старых сертификатов
12. Деактивация старого ACME-аккаунта
13. Проверка автоматического продления сертификатов
14. Проверка пользователей Ubuntu
    Проверка sudo
15. Аудит systemd-служб
    Проверка символических ссылок
    Проверка systemd generators
16. Проверка cron и systemd timers
17. Проверка SUID и SGID
18. Проверка Linux capabilities
19. Проверка целостности системных пакетов
20. Поиск изменений файлов в период инцидента
21. Проверка PAM и изменения файлов 17 октября
22. Проверка LD_PRELOAD и сценариев запуска оболочки
    Проверка shell startup
23. Аудит nginx reverse proxy
24. Проверка HTTP-соединений между nginx и backend
25. Проверка Authorization в nginx
26. Создание зашифрованного архива доказательств
    Подготовка списка файлов
    Шифрование через GPG
27. Перенос GPG-архива на Windows
    Скачивание через PSCP
    Проверка GPG на Windows
    Удаление временной копии
28. Дополнительный архив с ключом поддержки
29. Неожиданная проблема с домашним каталогом пользователя
    Исправление
30. Итоги проверки первого VPS
31. Что удалось сделать по итогам расследования
32. Чего эта проверка не может доказать
33. Какие меры я считаю необходимыми в дальнейшем
    Ротация прикладных секретов
    Улучшение межсерверных соединений
    Хранение материалов расследования
    Вопрос доверия к гипервизору
34. Заключение
Полезная документация





1. Исходные данные и характер инцидента​


Инцидент произошёл 17 октября 2026 года.

Согласно полученной информации, интересующий период продолжался с 12:27 до 22:34 по московскому времени.

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

Это принципиально другая ситуация.

Если злоумышленник получает достаточные полномочия на гипервизоре, ему могут стать доступны данные гостевой виртуальной машины без необходимости выполнять обычный вход через SSH.

В зависимости от конкретных возможностей атакующего речь может идти о:

  • чтении файлов виртуального диска;
  • получении копий виртуальных дисков или снимков;
  • доступе к приватным ключам и конфигурациям;
  • извлечении паролей и других секретов;
  • потенциальном вмешательстве в работу гостевой ОС.

При этом гостевая Ubuntu может не зафиксировать никаких подозрительных SSH-подключений.

Именно поэтому я сразу разделил расследование на две части.

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

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

Какие серверы я проверял​


В расследовании участвовали две виртуальные машины.

Первый сервер использовался для обслуживания инфраструктуры условного Проекта А.

Второй сервер выполнял роль внешнего nginx reverse proxy для условного Проекта Б.

Для иллюстрации дальнейших примеров примем:

Код:
VPS-1: 192.0.2.10
VPS-2: 198.51.100.20

Основной домен: example.com
Дополнительный домен: example.net

SSH-порт: 22222
Обычный пользователь: operator

Эти адреса и имена вымышленные.

На втором VPS использовались:

  • Ubuntu Server 24.04.3 LTS;
  • KVM;
  • nginx 1.24.0;
  • OpenSSH;
  • UFW;
  • Certbot 2.9.0;
  • Let's Encrypt;
  • QEMU Guest Agent;
  • systemd.

Внешний сервер принимал HTTPS-запросы и перенаправлял их на backend-серверы.

2. Почему я не стал сразу переустанавливать VPS​


После получения уведомления о потенциальной компрометации инфраструктуры естественным решением кажется немедленная переустановка операционной системы.

Но у такого подхода есть недостаток: вместе с системой можно потерять важные сведения о произошедшем.

Поэтому я сначала решил сохранить материалы расследования и оценить текущее состояние серверов.

Меня интересовали:

  • история загрузок и перезагрузок;
  • журналы аутентификации;
  • история пользовательских сеансов;
  • записи systemd journal;
  • списки пользователей;
  • системные службы и таймеры;
  • конфигурации SSH и nginx;
  • исторические сертификаты и приватные ключи;
  • признаки изменения системных файлов.

При этом я старался не изменять конфигурацию без необходимости.

Большинство диагностических команд выполнялись только на чтение.

Мой основной принцип: сначала собрать доказательства и понять состояние системы, затем выполнять изменения, которые действительно необходимы.

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

3. Первичная проверка Ubuntu​


Первым делом я собрал основную информацию о системе.

Bash:
date -Is
timedatectl
hostnamectl
uname -a
uptime
uptime -s

Затем изучил историю загрузок:

Bash:
journalctl --list-boots --no-pager

И историю входов:

Bash:
last -x -F -n 50

Для изучения неуспешных попыток входа можно дополнительно использовать:

Bash:
lastb -F -n 50

Последняя команда зависит от наличия и сохранности соответствующего журнала.

Неожиданный результат​


На втором VPS выяснилось, что виртуальная машина работала без перезагрузки с декабря 2025 года.

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

Этот факт не доказывает отсутствие постороннего доступа, но позволяет исключить некоторые сценарии, требующие обязательной перезагрузки гостевой ОС.

4. Анализ SSH-подключений​


Следующим этапом я проверил журналы SSH.

Bash:
journalctl -u sshd -u ssh
  --since "2026-10-17 12:27:00"
  --until "2026-10-17 22:34:00"
  --no-pager

Дополнительно можно искать записи об успешной и неуспешной аутентификации:

Bash:
zgrep -hiE
  'Accepted|Failed password|Invalid user|authentication failure'
  /var/log/auth.log*
  2>/dev/null

Я сопоставил найденные успешные подключения со своими известными адресами.

Неизвестных успешных SSH-входов в проверяемый период обнаружено не было.

Но здесь необходимо учитывать важную особенность.

Отсутствие посторонних SSH-входов не означает, что диск VPS не мог быть прочитан через гипервизор.

В рассматриваемом сценарии злоумышленнику вообще не обязательно проходить аутентификацию внутри гостевой системы.

Проверка эффективной конфигурации SSH​


Для проверки OpenSSH я использовал:

Bash:
sshd -T

И отдельную проверку параметров для пользователей:

Bash:
sshd -T -C user=root,host=localhost,addr=127.0.0.1

sshd -T -C user=operator,host=localhost,addr=127.0.0.1

В моей конфигурации действовали следующие параметры:

Код:
PermitRootLogin no
PubkeyAuthentication no
PasswordAuthentication yes
KbdInteractiveAuthentication no
AuthorizedKeysCommand none
TrustedUserCAKeys none
UsePAM yes

Это было фактическое состояние проверяемого VPS.

В общем случае для удалённого администрирования обычно предпочтительнее использовать собственные SSH-ключи с отключённой парольной аутентификацией.

Но во время расследования я не стал одновременно перестраивать все механизмы входа. Сначала необходимо было безопасно заменить потенциально раскрытые секреты и убедиться, что удалённый доступ остаётся работоспособным.

5. Обнаружение ключа технической поддержки провайдера​


Отдельно я проверил файлы authorized_keys.

Bash:
find /root /home
  -name authorized_keys
  -type f
  -printf '%m %u:%g %p\n'
  2>/dev/null

В одном из файлов обнаружился публичный SSH-ключ с комментарием, указывающим на его возможное использование технической поддержкой провайдера.

В обезличенном примере назовём его:

Код:
providerSupportKey

Ключ имел тип RSA 4096.

Сам факт наличия такого ключа не означает, что он использовался злоумышленником.

Однако после инцидента я решил убрать ненужный потенциальный канал административного доступа.

Сохранение ключа как доказательства​


Перед удалением я создал резервную копию файла.

Bash:
umask 077

cp -a
  /root/.ssh/authorized_keys
  /root/provider-support-authorized_keys.evidence

cmp
  /root/.ssh/authorized_keys
  /root/provider-support-authorized_keys.evidence

Затем получил отпечаток:

Bash:
ssh-keygen -lf
  /root/provider-support-authorized_keys.evidence

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

Отключение ненужного ключа​


В моём случае файл содержал только ключ поддержки.

После создания проверенной резервной копии я очистил его:

Bash:
: > /root/.ssh/authorized_keys

chmod 600 /root/.ssh/authorized_keys

Затем проверил конфигурацию SSH:

Bash:
sshd -t

Важно. Если в authorized_keys есть собственные ключи администратора, очищать файл полностью нельзя.

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

6. Ротация SSH host keys​


Следующим шагом я заменил серверные SSH host keys.

Эти ключи нужны для подтверждения подлинности SSH-сервера.

Если приватные host keys были скопированы с виртуального диска, злоумышленник потенциально мог использовать их при атаке с подменой сервера.

Поэтому я решил перевыпустить все используемые ключи.

Сохранение старых ключей​


Сначала создал защищённый каталог:

Bash:
umask 077

mkdir -p /root/ssh-hostkeys-old

cp -a
  /etc/ssh/ssh_host_*
  /root/ssh-hostkeys-old/

Старые ключи сохранил для расследования.

Генерация новых ключей​


Новые ключи подготовил отдельно:

Bash:
umask 077

install -d -m 700 /root/new-ssh-hostkeys

ssh-keygen -q -t ed25519 -N ''
  -f /root/new-ssh-hostkeys/ssh_host_ed25519_key

ssh-keygen -q -t ecdsa -b 256 -N ''
  -f /root/new-ssh-hostkeys/ssh_host_ecdsa_key

ssh-keygen -q -t rsa -b 4096 -N ''
  -f /root/new-ssh-hostkeys/ssh_host_rsa_key

После этого установил новые файлы:

Bash:
for type in ed25519 ecdsa rsa; do
    install -m 600 -o root -g root
      "/root/new-ssh-hostkeys/ssh_host_${type}_key"
      "/etc/ssh/ssh_host_${type}_key"

    install -m 644 -o root -g root \
      "/root/new-ssh-hostkeys/ssh_host_${type}_key.pub" \
      "/etc/ssh/ssh_host_${type}_key.pub"
done

Проверил конфигурацию:

Bash:
sshd -t

И перечитал настройки:

Bash:
systemctl reload sshd

При этом я оставил открытым действующее SSH-подключение.

Новое подключение проверил в отдельном окне PuTTY.

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

Проверка новых отпечатков​


Bash:
for key in /etc/ssh/ssh_host_*_key.pub; do
    ssh-keygen -lf "$key"
done

При следующем соединении PuTTY сообщил об изменении ключа сервера.

Я сравнил отпечаток с полученным непосредственно на VPS и подтвердил изменение.

Ротация SSH host keys была выполнена на обоих серверах.

7. Исправление дублирующегося SSH-порта​


Во время перезагрузки конфигурации OpenSSH обнаружилась ещё одна особенность.

Один и тот же порт был указан в двух файлах конфигурации.

В журнале появлялось сообщение:

Код:
Bind to port ... failed: Address already in use

Для поиска повторяющихся директив использовал:

Bash:
grep -RnE '^[[:space:]]*Port[[:space:]]+'
  /etc/ssh/sshd_config
  /etc/ssh/sshd_config.d/

После резервного копирования дополнительного конфигурационного файла я убрал повторное объявление порта.

Затем выполнил:

Bash:
sshd -t

systemctl reload sshd

journalctl -u sshd -n 30 --no-pager

Повторных ошибок привязки порта больше не наблюдалось.

В этой статье в качестве примера используется порт 22222. К моей фактической конфигурации он отношения не имеет.

8. Проверка сетевого доступа и UFW​


Далее я проверил, какие службы доступны извне.

Bash:
ss -lntup

ufw status verbose

ufw status numbered

На внешнем reverse proxy были необходимы:

  • 80/tcp — HTTP;
  • 443/tcp — HTTPS;
  • нестандартный TCP-порт для SSH.

Сначала сохранил конфигурацию UFW:

Bash:
umask 077

cp -a /etc/ufw /root/ufw-backup

Пример необходимых правил:

Bash:
SSH_PORT=22222

ufw default deny incoming
ufw default allow outgoing

ufw allow 80/tcp
ufw allow 443/tcp
ufw allow "${SSH_PORT}/tcp"

ufw status numbered

Внимание. На рабочем сервере нельзя выполнять подобные изменения вслепую.

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

В моём случае я пересмотрел старые правила и оставил только необходимые входящие порты для IPv4 и IPv6.

9. Проверка QEMU Guest Agent​


Особое внимание я уделил QEMU Guest Agent.

Этот компонент обеспечивает взаимодействие гипервизора и гостевой ОС.

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

Для начала проверил состояние службы:

Bash:
systemctl status qemu-guest-agent --no-pager

dpkg-query -W qemu-guest-agent

Затем изучил журнал за период инцидента:

Bash:
journalctl -u qemu-guest-agent
  --since "2026-10-17 12:27:00"
  --until "2026-10-17 22:34:00"
  --no-pager

В журнале встречались вызовы:

Код:
guest-ping called

Я не обнаружил в доступных записях подтверждений выполнения команд или изменения пользовательских паролей через Guest Agent.

Но сам журнал не является исчерпывающим доказательством отсутствия других операций на уровне гипервизора.

Блокировка чувствительных RPC​


Я решил не отключать Guest Agent полностью, а ограничить наиболее опасные RPC.

Для этого создал:

Код:
/etc/qemu/qemu-ga.conf

С конфигурацией:

Код:
[general]
block-rpcs=guest-exec,guest-exec-status,guest-file-open,guest-file-close,guest-file-read,guest-file-write,guest-file-seek,guest-file-flush,guest-set-user-password,guest-ssh-get-authorized-keys,guest-ssh-add-authorized-keys,guest-ssh-remove-authorized-keys

Она ограничивает выполнение команд, файловые операции, изменение паролей и управление SSH authorized keys.

Затем проверил конфигурацию:

Bash:
qemu-ga --dump-conf

Перезапустил службу:

Bash:
systemctl restart qemu-guest-agent

И повторно проверил:

Bash:
qemu-ga --dump-conf

systemctl status qemu-guest-agent --no-pager

Указанные RPC оказались заблокированы.

Ограничение QEMU Guest Agent не защищает от прямого доступа к виртуальному диску через гипервизор.

Также следует учитывать, что блокировка RPC может ограничить некоторые функции обслуживания и резервного копирования виртуальной машины.

10. Ротация сертификатов Let's Encrypt​


После SSH я занялся TLS-сертификатами.

На внешнем сервере использовалось несколько групп сертификатов:

  • основные домены example.com и example.net;
  • статические ресурсы static.example.com и static.example.net;
  • дополнительные сервисы feed.example.com и feed.example.net.

Все домены здесь условные.

Сертификаты обслуживались Certbot.

Стандартная структура каталогов:

Код:
/etc/letsencrypt/live/
/etc/letsencrypt/archive/
/etc/letsencrypt/renewal/
/etc/letsencrypt/accounts/

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

Проверка действующих сертификатов​


Bash:
certbot certificates

Проверил символические ссылки:

Bash:
find /etc/letsencrypt/live
  -maxdepth 2 -type l -ls

И файлы автоматического продления:

Bash:
find /etc/letsencrypt/renewal
  -maxdepth 1 -type f
  -printf '%p\n'

Каталог live обычно содержит ссылки на соответствующие версии сертификатов в archive.

Поэтому я не стал самостоятельно удалять или переименовывать файлы внутри структуры Certbot.

Создание нового ACME-аккаунта​


Сначала сохранил данные старого аккаунта в защищённый каталог расследования.

После этого зарегистрировал новый аккаунт Let's Encrypt.

Пример:

Bash:
certbot register
  --email admin@example.com
  --agree-tos
  --no-eff-email

Затем проверил:

Bash:
certbot show_account

Новый аккаунт использовал новый приватный ключ ACME.

Но регистрация нового аккаунта ещё не означает замену действующих сертификатов.

Перевыпуск с новыми приватными ключами​


В моём случае Certbot использовал метод проверки владения доменом через webroot:

Код:
/var/www/html

Условный пример:

Bash:
certbot certonly
  --webroot
  -w /var/www/html
  --cert-name example.com
  --force-renewal
  --key-type ecdsa
  --new-key
  --account "NEW_ACME_ACCOUNT_ID"
  -d example.com
  -d example.net
  -d www.example.com
  -d www.example.net

Аналогично перевыпустил сертификаты остальных групп доменов.

Важный момент: перед использованием команды необходимо проверить реальные имена сертификатов, список доменов, способ подтверждения владения и применимые лимиты Let's Encrypt.

Проверка TLS через OpenSSL​


После выпуска я проверил не только Certbot, но и сертификат, который действительно отдаёт nginx.

Bash:
echo | openssl s_client
  -connect 127.0.0.1:443
  -servername example.com
  2>/dev/null
  | openssl x509
      -noout
      -serial
      -dates
      -subject
      -issuer

Аналогично проверил остальные домены.

Новые сертификаты соответствовали активным версиям в каталогах Certbot.

Я также убедился, что перевыпуск сопровождался заменой приватных ключей.

11. Отзыв старых сертификатов​


После успешной ротации я отозвал старые, ещё действовавшие сертификаты.

Здесь важно понимать разницу между перевыпуском и отзывом.

Новый сертификат не делает прежний автоматически отозванным.

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

Я использовал причину:

Код:
keycompromise

Пример:

Bash:
certbot revoke
  --cert-path /etc/letsencrypt/archive/example.com/cert5.pem
  --key-path /etc/letsencrypt/archive/example.com/privkey5.pem
  --reason keycompromise
  --no-delete-after-revoke

Номера версий в примере условные.

Перед отзывом обязательно необходимо проверить, что указан исторический сертификат, а не активный.

На втором VPS я отозвал семь исторических сертификатов, относящихся к трём группам доменов.

Файлы сохранил для расследования, поэтому использовал параметр --no-delete-after-revoke.

В дальнейшем такие материалы необходимо учитывать при обслуживании Certbot, чтобы избежать случайного использования или продления отозванных сертификатов.

12. Деактивация старого ACME-аккаунта​


После выпуска новых сертификатов я деактивировал прежний аккаунт Let's Encrypt.

Пример:

Bash:
certbot unregister
  --account "OLD_ACME_ACCOUNT_ID"

Операция завершилась успешно.

Затем я проверил ссылки на аккаунты в настройках продления:

Bash:
grep -R '^account ='
  /etc/letsencrypt/renewal/

Все активные линии сертификатов использовали новый ACME-аккаунт.

Старый аккаунт я деактивировал только после проверки новых сертификатов.

13. Проверка автоматического продления сертификатов​


После ротации необходимо было убедиться, что Certbot продолжит нормально работать в будущем.

Проверил:

Bash:
systemctl status certbot.timer --no-pager

systemctl cat certbot.timer

systemctl cat certbot.service

Кроме того, на VPS присутствовал файл:

Код:
/etc/cron.d/certbot

Я проверил его содержимое.

Выяснилось, что cron-задание не выполняется при использовании systemd.

В конфигурации присутствовала проверка:

Bash:
test -x /usr/bin/certbot -a \! -d /run/systemd/system

Основным механизмом автоматического продления был certbot.timer.

После успешного обновления сертификатов предусматривалось перечитывание конфигурации nginx:

Bash:
systemctl reload nginx

Финальная проверка:

Bash:
certbot renew --dry-run

Все действующие сертификаты успешно прошли тест продления.

14. Проверка пользователей Ubuntu​


После ротации ключей я приступил к поиску возможных механизмов закрепления.

Начал с учётных записей.

Bash:
getent passwd | awk -F: '
$7 !~ /(nologin|false)$/ {
    printf "USER=%s UID=%s GID=%s HOME=%s SHELL=%s\n",
        $1,$3,$4,$6,$7
}'

На втором VPS присутствовали только ожидаемые пользователи.

Проверил UID 0:

Bash:
awk -F: '$3 == 0 {print}' /etc/passwd

Единственным пользователем с UID 0 оказался root.

Дополнительно проверил привилегированные группы:

Bash:
for group in sudo adm docker lxd libvirt; do
    getent group "$group"
done

Неизвестных пользователей в административных группах обнаружено не было.

Проверка sudo​


Bash:
visudo -c

Затем:

Bash:
find /etc/sudoers.d
  -maxdepth 1 -type f
  -printf '%m %u:%g %p\n'

И права обычного пользователя:

Bash:
sudo -l -U operator

Пользователь не обладал правами sudo.

Подозрительных дополнительных правил повышения привилегий не обнаружилось.

15. Аудит systemd-служб​


Следующим этапом я проверил включённые службы.

Bash:
systemctl list-unit-files
  --type=service
  --state=enabled
  --no-pager

На втором VPS находилось 17 включённых unit-файлов служб.

Затем проверил файлы в пользовательской части конфигурации systemd:

Bash:
find /etc/systemd/system
  -type f
  -printf '%TY-%Tm-%Td %TH:%TM %u:%g %p\n'
  2>/dev/null | sort

Среди них обнаружился только ранее созданный sshd.service.

Он использовался для штатного запуска SSH.

Подозрительных пользовательских служб не было.

Проверка символических ссылок​


Bash:
find /etc/systemd/system
  -type l
  -printf '%p -> %l\n'
  2>/dev/null | sort

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

Проверка systemd generators​


Отдельного внимания потребовала ссылка:

Код:
/etc/systemd/system-generators/systemd-gpt-auto-generator

Я проверил:

Bash:
stat
  /etc/systemd/system-generators/systemd-gpt-auto-generator

readlink -f
  /etc/systemd/system-generators/systemd-gpt-auto-generator

Оказалось, что ссылка указывает на:

Код:
/dev/null

Она использовалась для отключения стандартного генератора systemd.

Также я проверил её принадлежность установленному пакету:

Bash:
dpkg-query -S
  /etc/systemd/system-generators/systemd-gpt-auto-generator

Объект относился к пакету systemd.

Признаков вредоносного механизма запуска обнаружено не было.

16. Проверка cron и systemd timers​


Затем проверил пользовательские cron-задания.

Bash:
crontab -l -u root

crontab -l -u operator

Пользовательских заданий на втором VPS не оказалось.

После этого изучил системный cron:

Bash:
find
  /etc/cron.d
  /etc/cron.daily
  /etc/cron.hourly
  /etc/cron.weekly
  /etc/cron.monthly
  /var/spool/cron/crontabs
  -maxdepth 1 -type f
  -printf '%TY-%Tm-%Td %TH:%TM %u:%g %p\n'
  2>/dev/null | sort

Все найденные задания относились к ожидаемым системным операциям.

Дополнительно:

Bash:
systemctl list-timers --all --no-pager

На сервере было 11 таймеров.

Среди них присутствовали Certbot, APT, logrotate, fstrim и другие штатные задания обслуживания.

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

17. Проверка SUID и SGID​


Следующий важный этап — поиск файлов с SUID и SGID.

Bash:
find / -xdev -type f
  \( -perm -4000 -o -perm -2000 \)
  -printf '%m %u:%g %p\n'
  2>/dev/null | sort

На втором VPS обнаружился 21 файл с такими битами.

Среди них были стандартные системные программы:

  • su;
  • sudo;
  • passwd;
  • mount;
  • umount;
  • chfn;
  • chsh;
  • newgrp.

Затем я проверил, принадлежат ли найденные файлы установленным пакетам.

Bash:
find / -xdev -type f
  \( -perm -4000 -o -perm -2000 \)
  -print0 2>/dev/null |
while IFS= read -r -d '' file; do
    if ! dpkg-query -S -- "$file"
        >/dev/null 2>&1; then
        echo "NOT OWNED: $file"
    fi
done

Вывод оказался пустым.

Это означало, что неизвестных SUID/SGID-файлов вне учёта dpkg найдено не было.

Однако принадлежность пакету сама по себе ещё не является независимой проверкой целостности файла.

18. Проверка Linux capabilities​


Linux capabilities позволяют предоставлять процессам отдельные привилегии без полного набора прав root.

Для поиска файловых capabilities я использовал:

Bash:
getcap -r /usr /opt /root /etc 2>/dev/null

Единственной найденной записью оказалась:

Код:
/usr/bin/ping cap_net_raw=ep

Это обычная настройка, позволяющая использовать ICMP без полноценного доступа root.

Неизвестных исполняемых файлов с опасными возможностями вроде cap_setuid или cap_setgid обнаружено не было.

19. Проверка целостности системных пакетов​


Следующий этап — проверка важных компонентов Ubuntu.

Bash:
dpkg --verify
  sudo
  passwd
  login
  util-linux
  openssh-server
  openssh-client
  systemd
  qemu-guest-agent

echo "DPKG VERIFY EXIT CODE: $?"

Результат:

Код:
DPKG VERIFY EXIT CODE: 0

Также проверил:

Bash:
dpkg --verify
  base-files
  libpam-runtime
  libpam-modules
  libpam-modules-bin
  libpam0g
  systemd

echo "DPKG VERIFY EXIT CODE: $?"

Результат снова оказался нулевым.

Таким образом, локальный механизм проверки пакетов не обнаружил отклонений.

Но этот результат нельзя считать абсолютной гарантией отсутствия вмешательства.

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

20. Поиск изменений файлов в период инцидента​


Для поиска возможных следов вмешательства я проверил время изменения файлов.

Bash:
TZ=Europe/Moscow find
  /etc /usr/local /opt /root /home
  -xdev -type f
  -newermt '2026-10-17 12:27:00'
  ! -newermt '2026-10-17 22:34:00'
  -printf '%TY-%Tm-%Td %TH:%TM:%TS %u:%g %p\n'
  2>/dev/null | sort

На втором VPS файлов с временем модификации внутри заданного интервала в проверенных каталогах обнаружено не было.

Но у метода есть ограничения.

Злоумышленник может восстановить временные метки.

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

Поэтому данную проверку я рассматривал исключительно как дополнительный источник информации.

21. Проверка PAM и изменения файлов 17 октября​


Во время проверки я обнаружил, что несколько файлов PAM были изменены 17 октября приблизительно в 06:49.

Речь шла о:

Код:
/etc/pam.d/common-auth
/etc/pam.d/common-account
/etc/pam.d/common-password
/etc/pam.d/common-session
/etc/pam.d/common-session-noninteractive

Первоначально это вызвало вопросы.

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

Однако время изменения файлов оказалось раньше заявленного периода инцидента.

Я решил проверить историю обновлений.

Bash:
zgrep -hE '^2026-10-17 06:(4[0-9]|5[0-9])'
  /var/log/dpkg.log*
  2>/dev/null | tail -n 100

Затем изучил журнал systemd:

Bash:
journalctl
  --since "2026-10-17 06:40:00"
  --until "2026-10-17 07:00:00"
  --no-pager

Выяснилось, что в этот период выполнялся:

Код:
apt-daily-upgrade.service

В частности, обновлялись:

Код:
systemd
libpam-systemd
openssh-server

Изменение PAM совпало по времени с настройкой libpam-systemd.

Кроме того, проверка целостности пакетов PAM завершилась успешно.

Вывод: обнаруженные изменения согласовывались со штатным автоматическим обновлением Ubuntu.

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

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

22. Проверка LD_PRELOAD и сценариев запуска оболочки​


Отдельно я проверил потенциальные механизмы подмены системных программ.

Для начала:

Bash:
if [ -e /etc/ld.so.preload ]; then
    ls -l /etc/ld.so.preload
    cat /etc/ld.so.preload
else
    echo "OK: /etc/ld.so.preload absent"
fi

Файл отсутствовал.

Затем проверил переменные загрузчика:

Bash:
env | grep -E
  '^(LD_PRELOAD|LD_LIBRARY_PATH|LD_AUDIT)='
  || echo "No LD_* overrides"

Необычных переопределений обнаружено не было.

Также проверил:

Bash:
find /etc/ld.so.conf.d
  -maxdepth 1 -type f
  -printf '%m %u:%g %p\n'

Проверка shell startup​


Я изучил глобальные и пользовательские файлы запуска оболочки:

Bash:
ls -la
  /etc/profile
  /etc/bash.bashrc
  /etc/profile.d/
  /root/.profile
  /root/.bashrc

Затем выполнил поиск потенциально интересных команд:

Bash:
grep -RnEi
  '(curl|wget|nc |netcat|socat|base64|eval |LD_PRELOAD|/dev/tcp/|bash -c|sh -c)'
  /etc/profile
  /etc/bash.bashrc
  /etc/profile.d/
  /root/.profile
  /root/.bashrc
  2>/dev/null

Среди совпадений находились обычные команды настройки окружения.

Дополнительно проверил происхождение locale-check, вызываемого из:

Код:
/etc/profile.d/01-locale-fix.sh

Команда:

Bash:
dpkg-query -S
  /usr/bin/locale-check
  /etc/profile.d/01-locale-fix.sh

показала, что оба файла относятся к пакету base-files.

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

23. Аудит nginx reverse proxy​


После системного аудита я проверил назначение второго VPS.

Сначала получил список серверных компонентов:

Bash:
dpkg-query -W -f='${binary:Package} ${Version}\n'
  'nginx*' 'php*' 'mysql*' 'mariadb*'
  'percona*' 'redis*' 'sphinx*'
  2>/dev/null | sort

Затем проверил запущенные службы:

Bash:
systemctl list-units
  --type=service
  --state=running
  --no-pager

И слушающие порты:

Bash:
ss -lntp

На втором VPS не обнаружилось работающих PHP-FPM, MySQL, MariaDB, Redis или Sphinx.

Сервер использовался преимущественно как nginx reverse proxy.

Дополнительно я поискал конфигурации веб-приложений:

Bash:
find /var/www /srv /opt
  -xdev -type f
  \( -name '.env'
     -o -name '.env.local'
     -o -name 'config.php'
     -o -name 'database.php'
     -o -name 'config.inc.php'
     -o -name 'wp-config.php'
     -o -name 'settings.php'
  \)
  -printf '%m %u:%g %p\n'
  2>/dev/null | sort

Типичных файлов конфигураций PHP-приложений обнаружено не было.

Это уменьшало количество потенциально раскрытых прикладных секретов непосредственно на данном VPS.

Но не исключало секреты в конфигурации самого nginx.

24. Проверка HTTP-соединений между nginx и backend​


Следующим этапом я изучил конфигурацию обратного проксирования.

Bash:
nginx -t

Синтаксис конфигурации был корректным.

Затем я проверил директивы proxy_pass.

На VPS использовалось два блока upstream и восемь направлений проксирования.

Все они использовали HTTP.

Условная схема:

Код:
Пользователь
    |
    | HTTPS
    v
Внешний nginx
    |
    | HTTP
    v
Backend-сервер

Затем я проверил расположение backend-адресов.

Они оказались публично маршрутизируемыми, а соединения выполнялись через обычный сетевой интерфейс.

Типовых активных VPN-туннелей на VPS не обнаружилось.

Важный вывод: HTTPS между браузером и внешним nginx не гарантирует шифрование соединения между nginx и backend.

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

В моём случае часть инфраструктуры была связана с BitTorrent, где HTTP announce-запросы могут использоваться намеренно.

Однако если в URL анонсера передаётся персональный passkey, он также передаётся без TLS-защиты.

Во время расследования я не стал менять работающую схему проксирования.

В дальнейшем для таких соединений можно рассмотреть:

  • WireGuard;
  • либо HTTPS между nginx и backend с проверкой сертификата.

При использовании HTTPS до backend необходимо корректно настроить SNI и проверку сертификата. Простая замена http:// на https:// недостаточна.

25. Проверка Authorization в nginx​


Во время поиска возможных секретов я обнаружил две директивы:

NGINX:
proxy_set_header Authorization "";

Изначально возникло предположение, что в них может находиться статический пароль для backend.

Поэтому я проверил реальные значения.

Выяснилось, что оба значения пустые.

Такая конфигурация не добавляет пароль. Напротив, она предотвращает передачу заголовка Authorization на backend.

Следовательно, подозрение на наличие статических секретов в этих директивах не подтвердилось.

Менять их не потребовалось.

Это ещё раз показало, что результаты поиска по словам password, secret, token или Authorization необходимо интерпретировать в контексте соответствующей конфигурации.

26. Создание зашифрованного архива доказательств​


После завершения ротации ключей я решил сохранить исторические материалы расследования.

В основной архив вошли:

  • старые SSH host keys;
  • исторические TLS-сертификаты;
  • старые TLS-приватные ключи;
  • данные прежнего ACME-аккаунта;
  • резервные копии конфигураций Certbot;
  • старые конфигурации SSH;
  • список включённых файлов.

Поскольку среди материалов находились приватные ключи, архив необходимо было зашифровать.

Для этого я использовал TAR и GPG.

Подготовка списка файлов​


Сначала составил список материалов:

Код:
/root/incident-evidence/files.txt

В него включил только заранее проверенные исторические файлы.

Новые активные TLS-ключи в основной архив старых секретов не включал.

Шифрование через GPG​


Bash:
umask 077

export GPG_TTY="$(tty)"

set -o pipefail

tar -C / -czf -
  -T /root/incident-evidence/files.txt
| gpg
    --symmetric
    --cipher-algo AES256
    --s2k-digest-algo SHA512
    --compress-algo none
    --output /root/incident-evidence.tar.gz.gpg

Архив создавался потоком.

Это позволило не оставлять дополнительную незашифрованную копию всего набора доказательств.

После создания я проверил его содержимое:

Bash:
set -o pipefail

gpg --decrypt
  /root/incident-evidence.tar.gz.gpg
| tar -tzf -

echo "ARCHIVE CHECK EXIT CODE: $?"

Ожидаемый код успешной проверки:

Код:
ARCHIVE CHECK EXIT CODE: 0

Дополнительно проверил права:

Bash:
stat -c '%a %U:%G %s %n'
  /root/incident-evidence.tar.gz.gpg

Для приватного архива были установлены права:

Код:
600 root:root

Затем вычислил SHA-256:

Bash:
sha256sum
  /root/incident-evidence.tar.gz.gpg

Контрольную сумму сохранил отдельно.

27. Перенос GPG-архива на Windows​


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

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

Bash:
install -d -m 700
  -o operator
  -g operator
  /var/tmp/operator-evidence

install -m 600
  -o operator
  -g operator
  /root/incident-evidence.tar.gz.gpg
  /var/tmp/operator-evidence/

После этого проверил SHA-256 временного файла:

Bash:
sha256sum
  /var/tmp/operator-evidence/incident-evidence.tar.gz.gpg

Контрольная сумма совпала.

Скачивание через PSCP​


На Windows я использовал PowerShell и PSCP из комплекта PuTTY.

Пример команды:

Код:
& "C:\Program Files\PuTTY\pscp.exe" -P 22222 "operator@192.0.2.10:/var/tmp/operator-evidence/incident-evidence.tar.gz.gpg" "$env:USERPROFILE\Downloads\"

Здесь:

  • 192.0.2.10 — вымышленный IP;
  • 22222 — условный SSH-порт;
  • operator — условный пользователь.

После передачи проверил архив:

Код:
$archive = "$env:USERPROFILE\Downloads\incident-evidence.tar.gz.gpg"

Get-FileHash -Algorithm SHA256 $archive

Контрольные суммы на Windows и Linux совпали.

Таким образом, я подтвердил, что зашифрованный файл был передан без изменений.

Проверка GPG на Windows​


Для проверки расшифровки использовал GnuPG.

Код:
& "C:\Program Files\GnuPG\bin\gpg.exe" --pinentry-mode loopback --output - --decrypt $archive > $null

Write-Host "GPG EXIT CODE: $LASTEXITCODE"

При корректной расшифровке GPG завершается без ошибок проверки данных.

Ранее я также проверил структуру TAR непосредственно на Linux.

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

Удаление временной копии​


После завершения переноса я удалил временный файл:

Bash:
rm -f
  /var/tmp/operator-evidence/incident-evidence.tar.gz.gpg

rmdir /var/tmp/operator-evidence

Оригинальный зашифрованный архив в каталоге root сохранил.

28. Дополнительный архив с ключом поддержки​


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

Чтобы не менять ранее проверенный файл, я сделал дополнительный GPG-архив.

Сначала проверил исходный ключ:

Bash:
ssh-keygen -lf
  /root/provider-support-authorized_keys.evidence

Затем создал отдельный архив:

Bash:
umask 077
export GPG_TTY="$(tty)"
set -o pipefail

tar -C / -czf -
  root/provider-support-authorized_keys.evidence
| gpg --symmetric
    --cipher-algo AES256
    --s2k-digest-algo SHA512
    --compress-algo none
    --output /root/provider-support-evidence.tar.gz.gpg

После создания выполнил:

Bash:
set -o pipefail

gpg --decrypt
  /root/provider-support-evidence.tar.gz.gpg
| tar -tzf -

Затем сравнил контрольные суммы:

Bash:
sha256sum
  /root/provider-support-evidence.tar.gz.gpg

Дополнительный архив также был перенесён на Windows.

Проверка SHA-256 на локальном компьютере полностью совпала с серверной.

При проверке GPG на Windows первоначально возникла ошибка парольной фразы. После перезапуска GPG Agent и повторной расшифровки она исчезла.

Отдельно возникла особенность Windows при использовании --output NUL. GPG пытался переименовать временный файл NUL.part и завершался с ошибкой.

Поэтому для последующих проверок я использовал --output - с перенаправлением стандартного вывода.

Оригинал дополнительного архива и исходный файл-доказательство сохранил в защищённом каталоге root.

29. Неожиданная проблема с домашним каталогом пользователя​


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

В обезличенном примере:

Код:
operator:x:1000:1000::/home/operator:/bin/sh

Однако каталога /home/operator не существовало.

Проверил:

Bash:
getent passwd operator

id operator

ls -ld
  /home
  /home/operator
  /etc/skel

Затем выполнил тест:

Bash:
runuser -u operator -- sh -c '
    printf "HOME=%s\n" "$HOME"
    cd "$HOME" 2>&1
    pwd
'

Система сообщила, что перейти в домашний каталог невозможно.

В журналах не обнаружилось достоверного объяснения его отсутствия.

Возможно, пользователь был создан без домашнего каталога при первоначальной настройке VPS.

Но подтвердить эту версию не удалось.

Исправление​


Я создал каталог с правильными правами:

Bash:
install -d -m 700
  -o operator
  -g operator
  /home/operator

Затем проверил:

Bash:
stat -c '%a %U:%G %n' /home/operator

Результат:

Код:
700 operator:operator /home/operator

Повторный тест:

Bash:
runuser -u operator -- sh -c '
    cd "$HOME" &&
    echo "HOME DIRECTORY OK" &&
    pwd
'

Каталог стал доступен пользователю.

Перезапуск SSH не потребовался.

Отсутствие домашнего каталога само по себе не было подтверждением взлома.

30. Итоги проверки первого VPS​


Первый VPS я проверял по той же основной методике.

В частности, исследовал:

  • историю входов и журналы SSH;
  • пользователей и административные полномочия;
  • systemd-службы;
  • cron и таймеры;
  • SUID/SGID;
  • Linux capabilities;
  • целостность системных пакетов;
  • конфигурацию QEMU Guest Agent;
  • SSH host keys;
  • TLS-сертификаты;
  • ACME-аккаунты.

На первом сервере также присутствовал ключ технической поддержки провайдера.

Я сохранил его для расследования и исключил из действующего authorized_keys.

Затем выполнил ротацию SSH host keys, TLS-сертификатов и ACME-аккаунта.

Ограничил чувствительные операции QEMU Guest Agent.

Исторические ключи и конфигурации сохранил в зашифрованном архиве.

По результатам выполненных проверок подтверждённых следов постороннего входа или закрепления в гостевой ОС не обнаружилось.

Но я не стал делать вывод, что данные сервера гарантированно не были доступны на уровне гипервизора.

31. Что удалось сделать по итогам расследования​


После завершения технических проверок я подвёл общий итог по обоим VPS.

SSH и пользователи

  • Проверил историю успешных входов.
  • Изучил конфигурацию OpenSSH.
  • Проверил пользователей и sudo.
  • Сменил пароли административных учётных записей.
  • Перевыпустил SSH host keys.
  • Удалил ненужные ключи поддержки провайдера из действующей авторизации.
  • Проверил работу SSH после изменений.

TLS и Let's Encrypt

  • Проверил действующие сертификаты.
  • Сохранил исторические ключи.
  • Создал новые ACME-аккаунты.
  • Перевыпустил TLS-сертификаты с новыми ключами.
  • Отозвал старые действовавшие сертификаты.
  • Деактивировал прежние ACME-аккаунты.
  • Проверил работу HTTPS.
  • Проверил автоматическое продление Certbot.

Операционная система

  • Изучил журналы событий.
  • Проверил systemd и cron.
  • Проверил SUID/SGID.
  • Проверил Linux capabilities.
  • Проверил целостность системных пакетов.
  • Исследовал изменения PAM.
  • Проверил LD_PRELOAD.
  • Изучил сценарии запуска оболочки.

Инфраструктура

  • Ограничил опасные RPC QEMU Guest Agent.
  • Пересмотрел сетевые правила UFW.
  • Проверил nginx reverse proxy.
  • Проанализировал межсерверные HTTP-соединения.
  • Проверил потенциальные секреты в конфигурации nginx.

Материалы расследования

  • Создал зашифрованные GPG-архивы.
  • Проверил структуру архивов через TAR.
  • Скачал архивы на Windows.
  • Сверил контрольные суммы SHA-256.
  • Удалил временные копии после переноса.

32. Чего эта проверка не может доказать​


Несмотря на подробный аудит, существуют объективные ограничения.

1. Отсутствие SSH-входов не исключает чтение диска.

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

2. Проверка dpkg не гарантирует абсолютную целостность ОС.

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

3. Временные метки не являются неопровержимыми доказательствами.

Их можно восстановить или изменить.

4. Ограничение Guest Agent не устраняет риски гипервизора.

Прямой доступ к дискам и памяти не зависит от RPC гостевого агента.

5. Замена секретов не отменяет возможную прошлую утечку.

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

33. Какие меры я считаю необходимыми в дальнейшем​


После завершения первоначального расследования я выделил несколько дополнительных задач.

Ротация прикладных секретов​


На серверах, где непосредственно работают приложения и базы данных, следует проверить:

  • пароли СУБД;
  • секреты PHP-приложений;
  • API-токены;
  • ключи сессий;
  • учётные данные систем резервного копирования;
  • ключи межсерверной авторизации.

Если подобные данные находились на потенциально доступном виртуальном диске, их необходимо рассматривать как потенциально раскрытые.

Улучшение межсерверных соединений​


Для соединений внешнего nginx с backend-серверами можно использовать WireGuard или HTTPS с обязательной проверкой сертификатов.

Это уменьшает риск перехвата данных на промежуточных сетевых узлах.

Хранение материалов расследования​


Исторические приватные ключи и конфигурации необходимо хранить в зашифрованном виде.

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

Особенно осторожно следует обращаться с каталогами Certbot, поскольку неправильное ручное удаление файлов может нарушить автоматическое продление сертификатов.

Вопрос доверия к гипервизору​


Наконец, остаётся инфраструктурный риск.

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

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

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

34. Заключение​


Расследование инцидента с гипервизором оказалось значительно сложнее обычной проверки SSH-журналов.

Мне потребовалось последовательно изучить два VPS, проверить механизмы закрепления в Ubuntu, заменить криптографические ключи, перевыпустить сертификаты и сохранить исторические материалы расследования.

В ходе проверок я не обнаружил подтверждённых признаков постороннего входа или закрепления в гостевых операционных системах.

При этом удалось устранить несколько потенциальных рисков:

  • заменить старые SSH host keys;
  • исключить ненужные ключи технической поддержки;
  • перевыпустить TLS-сертификаты;
  • отозвать исторические действовавшие сертификаты;
  • заменить ACME-аккаунты;
  • ограничить чувствительные операции QEMU Guest Agent;
  • проверить и уточнить сетевые правила;
  • сохранить материалы расследования в зашифрованном виде.

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

Отсутствие следов компрометации внутри Ubuntu не доказывает, что злоумышленники не могли прочитать данные виртуальной машины через гипервизор.

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

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

Для себя я определил следующую последовательность действий:

Сохранение доказательств → аудит системы → ротация секретов → проверка работоспособности → оценка оставшихся рисков → решение о дальнейшем размещении VPS.

Именно такой подход я применил при расследовании инцидента с двумя своими виртуальными серверами.




Полезная документация​


Для изучения описанных механизмов полезны официальные руководства:

  • QEMU Guest Agent — документация и описание RPC.
  • OpenSSH — руководство по настройке сервера и управлению host keys.
  • Certbot — руководство по получению, продлению и отзыву сертификатов.
  • nginx — документация модуля HTTP Proxy.
  • GnuPG — руководство по симметричному шифрованию.
  • Ubuntu Manpages — справочная документация по системным утилитам Linux.
Об авторе
Guru
Василий, cистемный админ /gnu/linux/windows/macos/mikrotik/troubleshooter, создатель сайта
Интересуюсь всем что делает инфраструктуру быстрой и надёжной
Открыт к общению и проектам, написать мне можно через форму или в личном сообщении

❗ Если есть пожелания по обзору какого-либо вопроса не представленного на сайте - пиши в комментариях

Комментарии

Нет комментариев для отображения.

Информация о статье

Автор
Guru
Время чтения статьи
24 мин чтения
Просмотры
38
Посл. обновление

Ещё в Linux

Ещё от Guru

Поделиться этой статьёй

Назад
Верх