Files
knowledge-base/decisions/2026-04-24-finland-vps-malware-cleanup.md
2026-04-24 15:30:00 +03:00

77 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
date: 2026-04-24
type: incident
tags: [niikn, vpn, security, malware, finland]
---
# Finland VPS 78.17.4.225 — инцидент XorDDoS + очистка
## Обстоятельства
- 24 Apr провайдер adminvps.ru заблокировал сервер за **14 ТБ трафика за ~11 дней** (~1.27 ТБ/день)
- Олег доплатил +8 ТБ, сервер снова в сети
- AmneziaVPN НИИКН (клиенты через OpenWrt 10.8.1.16) всё это время работал, но на фоне шёл malware
## Диагноз
Семейство **Linux/XorDDoS** (или близкий вариант). Маскировки:
- `/usr/bin/zneirjeklr` — главный бинарь, cmdline `[rcu_gp]` (под kernel thread)
- `/etc/init.d/zneirjeklr` — SysV init persistence (автогенерит systemd unit)
- `/etc/cron.hourly/gcc.sh` — backup persistence, cp из `/lib/libudev.so` в `/lib/libudev.so.6` и запуск
- `/usr/local/bin/lvm2-monitor` — под LVM monitor
- `/lib/libudev.so` + `/usr/lib/libudev.so` — под libudev
- `/tmp/*` + `/var/tmp/*` — дропперы с числовыми именами (3.2 МБ каждый)
- `/var/tmp/QvqDAQNp` — UPX-packed дроппер (14 МБ)
- cmdline `hald-runner` / `mingetty tty1` — фейковые имена процессов
## Хронология (по mtime)
| Дата | Событие |
|------|---------|
| 28 Mar 23:59 | Первый успешный `Accepted password` с 172.18.0.3 (panel-web legitimate или уже compromised) |
| 7 Apr 19:44 | Дроппер `/var/tmp/QvqDAQNp` создан |
| 13 Apr 5:54-5:59 | Массовое создание 7 дропперов в `/var/tmp/` |
| 17 Apr 17:33 | Ещё волна (EXT4 remount в dmesg) |
| 20 Apr 02:13 | `zneirjeklr.service` активирован (systemd-sysv-generator) |
| 23 Apr 14:49 | Провайдер остановил сервер (квота) |
| 24 Apr 11:40 | Олег оплатил, сервер поднялся — malware сразу запустился |
| 24 Apr 12:00-12:30 | Очистка |
## C2 инфраструктура
- 141.98.10.115:1531
- 170.168.103.27:29205
- 64.89.161.144:40778
## Точка входа
**RCE в PHP-панели AmneziaVPN (`amnezia-panel-web`)** — НЕ SSH brute-force.
Доказательство: единственные успешные `Accepted password` в auth.log — с 176.62.183.186 (Олег) и 172.18.0.3 (панель, легитимный `collect_metrics.php`). **Ни одного Accepted с внешнего malware-IP.**
Брут извне был (91.142.77.101: 67k, 91.142.78.60: 66k, 91.142.78.8: 36k попыток) — НЕ пробил.
## Что сделано
1. **Блок C2**`iptables -I OUTPUT -d <C2> -j DROP` × 3
2. **Kill + empty + chattr +i** на все 10 malware-файлов (пересоздаются но с нулевым содержимым и immutable — записаться не могут)
3. **SSH усилен:**
- Убран `PubkeyAuthentication no` из `/etc/ssh/sshd_config.d/99-cloud-init.conf` (cloud-init ставил по умолчанию — вот почему раньше входили только паролем)
- `PasswordAuthentication no` везде
- Новый root пароль `Ztey8pwWBiNNiMU09y76` (сохранён в `/root/.new_root_pw`), но по сути пароль уже не используется
4. **Docker→host SSH заблокирован:** `iptables -I INPUT -s 172.17.0.0/16 -p tcp --dport 22 -j DROP` (× 4 сети). **Важно:** это ломает `amnezia-panel/collect_metrics.php` — панель больше не получает метрики хоста. ВПН-туннели работают.
5. **fail2ban** установлен, active. Whitelist для docker сетей добавлен в `/etc/fail2ban/jail.d/docker-ignore.conf`.
6. **iptables-persistent** — правила сохранены в `/etc/iptables/rules.v4`, выживут reboot.
## Forensic артефакты (на сервере)
- `/root/forensic-20260424/zneirjeklr.bin` — копия бинарника
- `/root/forensic-20260424/1380609993.bin` — копия второй стадии
- `/root/clean-*.log` — лог очистки
- `/root/.ssh/authorized_keys.bak-20260424` — бэкап authorized_keys до дедупликации
## Что ещё надо (не сделано)
1. **Обновить/пересобрать amnezia-panel-web** — там PHP-RCE, может вернуться (текущий образ `amneziavpnphp_web` из `/opt/amneziavpnphp/docker-compose.yml`)
2. **Восстановить метрики панели** — либо положить SSH-ключ из контейнера в authorized_keys хоста, либо отключить `collect_metrics.php`
3. Мониторинг: `vnstat -d` раз в сутки, алерт при >50 ГБ/день
4. Через ~24 часа проверить `iptables -nvL OUTPUT | grep DROP` — если счётчики всё ещё растут = остался watchdog
5. Проверить другие контейнеры (amnezia-panel-db, vpn-nginx) на заражение
## Как заходить теперь
```bash
ssh -i ~/.ssh/id_ed25519 root@78.17.4.225 # только ключ
# Пароль sshpass больше не работает (PasswordAuthentication=no)
```