Files
knowledge-base/decisions/2026-04-24-finland-vps-malware-cleanup.md
dttb e2f166e416 Finland VPS 78.17.4.225: инцидент XorDDoS — очистка и hardening
- 14 ТБ трафика за 11 дней через ботнет (zneirjeklr/lvm2-monitor)
- Точка входа: RCE в amnezia-panel-web (PHP), не SSH brute
- Malware зачищен: 3 процесса, 10 файлов → 0-byte + chattr +i
- C2 IP заблокированы в iptables OUTPUT
- SSH: PasswordAuth=no, только ключ (исправлено 99-cloud-init.conf)
- Docker→host SSH в INPUT DROP (172.17/18/19/29)
- fail2ban + iptables-persistent
- Через 3ч проверка: чисто, watchdog'ов нет
- AmneziaVPN не пострадал, клиенты НИИКН онлайн
2026-04-26 22:07:11 +03:00

111 lines
7.2 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)
```
## Проверка через 3 часа после очистки (24 Apr ~15:30 UTC)
**Всё устойчиво:**
- Malware-процессов: 0
- Внешних подозрительных соединений: 0
- Файлы-ловушки целы (0 байт + `chattr +i`), новых дропперов в /tmp/var/tmp нет
- C2 OUTPUT DROP счётчики **не растут** (только +6 пакетов на 170.168.103.27 — доумирающие TCP-ретраи): 95 / 80 / 21
- INPUT DROP `amnezia-panel→host:22` — 10,563 пакетов (легитимный collect_metrics.php каждую минуту, безвреден)
- fail2ban: 54 IP забанены за сутки, 1211 failed отбито
- vnstat: вчера 1.77 GiB, сегодня 749 MiB (92 kbit/s) — **норма** (раньше 120 Мбит/с при заражении)
- AmneziaWG: handshake свежий, клиенты НИИКН активны, передано 2.03 GiB
**Очистка устойчива. Watchdog'ов не осталось. Сервер можно оставить в работе.**
## Хеши malware (для blocklist)
Сохранены в `/root/forensic-20260424/`:
- `zneirjeklr.bin` (114779 байт) — главный бинарь
- `1380609993.bin` (3301552 байт) — вторая стадия
## Сетевые IOC (Indicators of Compromise)
**C2 IP (заблокированы в OUTPUT):**
- 141.98.10.115:1531
- 170.168.103.27:29205
- 64.89.161.144:40778
**Brute-force источники (топ-10 за период до очистки):**
- 91.142.77.101 — 67,267 попыток
- 91.142.78.60 — 66,472
- 91.142.78.8 — 36,116
- 176.120.22.13 — 5,164
- 223.76.107.28 — 5,131
- 80.66.66.70 — 3,128
Эти IP уже автоматически попадают в fail2ban при появлении.