Сегодня (mmfb / LionART 1C): - projects/mmfb/lionart-1c.md — новый файл: VM 100 на pve LionART (WIN-70M2VEJIKEF, 10.253.1.240, Win Server 2022, 1С+SQL+Effector Saver), SSH-доступ claude/Kl@udeD1ag!2026 заведён, RDP под Администратор + 2FA. - projects/mmfb/proxmox-inventory.md — hostname WIN-70M2VEJIKEF в VM 100. - decisions/2026-05-28-mmfb-effector-saver-locked-admin.md — диагноз цикла 7038 (SCM-пароль разъехался с .\Администратор) + lockout учётки, и пошаговое решение (disable службы → ADSI unlock → LogonUser-проверка → sc.exe config password= → start auto). Накопившийся backlog (без отдельной правки в эту сессию): - decisions/: buzharovo (recon, migration-plan, 1c-licensing), sergey (instagram iPhone fakeip), amneziavpn macOS v1/v2 incompat, benelux compromise 2026-05-20, glavtorg autologon off, omni domain+update. - projects/: benilux README, buzharovo README+server1c, dttb (nextcloud-talk-bot, npm-proxy-hosts, proxmox-inventory, vpn-clients), glavtorg, sergey README, projects/_index. - claude-memory/: benelux, omniroute. - snippets/mac-dictation/groq-dictate.sh. - notes/claude/: ~80 авто-сохранённых транскриптов сессий за май. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
160 lines
13 KiB
Markdown
160 lines
13 KiB
Markdown
---
|
||
date: 2026-05-20
|
||
type: decision
|
||
tags: [security, incident, benelux, openwrt, ssh, firewall]
|
||
status: closed
|
||
severity: high
|
||
---
|
||
|
||
# Бенелюкс OpenWrt — взлом через SSH brute-force на WAN
|
||
|
||
## Что произошло
|
||
|
||
В ходе плановой проверки в **15:38 MSK** на `OpenWrt Benelux` (Cudy TR3000, NetBird `100.70.207.97`, WAN `45.143.21.60`) обнаружена активная компрометация:
|
||
|
||
- **LA = 4.0** на 4-ядерном MT7981, CPU 82% idle (нагрузка не на CPU, а на сеть+OOM-loop)
|
||
- **19 параллельных SSH-сессий** от чужих IP: `185.244.183.107` (RU), `51.77.53.0/24` и `51.38.148.97` (OVH FR), `108.181.123.93`, `51.75.55.2`
|
||
- Каждая сессия рассылала **спам через SMTP 25/465/587** на сотни IP (десятки соединений на момент анализа)
|
||
- Также параллельно — попытки на **Docker API 2375** (поиск открытых демонов для распространения)
|
||
- Cron `@reboot /tmp/.2424` (тело уже самоудалилось)
|
||
- `/root/.bash_history` и `.ash_history` отсутствуют — следы зачищены
|
||
|
||
## Вектор атаки
|
||
|
||
**SSH-сервер слушал на WAN (eth0)**, пароль `root:1qaz!QAZ` — общий по всей инфраструктуре. WAN IP `45.143.21.60` публичный → brute force с открытого интернета. После взлома атакующие держали постоянные авторизованные сессии и из своих shell-ов запускали спам напрямую.
|
||
|
||
> Ранняя гипотеза о malware-процессах под именами `systemd`/`sshd` оказалась ложной — это были обычные процессы атакующих в их собственных dropbear-shell. На OpenWrt нет ни systemd, ни sshd; имена `dropbear` в `netstat` — это родительские SSH-сессии злоумышленников.
|
||
|
||
## Что сделано (без ребута)
|
||
|
||
| Шаг | Команда / артефакт |
|
||
|---|---|
|
||
| 1. Заблокировать спам | `nft insert rule inet fw4 output oifname eth0 tcp dport {25,465,587,2375} drop` (+ `forward`) |
|
||
| 2. Заблокировать вход SSH с WAN | `nft insert rule inet fw4 input iifname eth0 tcp dport 22 drop` |
|
||
| 3. Убить 19 атакующих сессий | `kill -9` всех `dropbear` PID с не-NetBird foreign IP |
|
||
| 4. Положить ключ | `/etc/dropbear/authorized_keys` = mac-ed25519 (см. `~/.ssh/id_ed25519.pub`) |
|
||
| 5. Поменять пароль root | новый — в auto-memory (НЕ в vault) |
|
||
| 6. Удалить вредоносную крон-запись | `@reboot /tmp/.2424` вычищено, осталось только `13 9 * * * /usr/bin/podkop list_update` |
|
||
| 7. Persist firewall | `/etc/nftables.d/99-incident-20260520.nft` + `fw4 reload` |
|
||
|
||
После `fw4 reload` роутер автоматически ребутнулся (вероятно watchdog отреагировал на reload в момент OOM-loop). После ребута: правила подхватились из `/etc/nftables.d/`, ключ сработал, новый пароль активен, cron чистый.
|
||
|
||
## Результат
|
||
|
||
| Метрика | До | После |
|
||
|---|---|---|
|
||
| Load average | 4.04 | 0.15 |
|
||
| Free RAM | ~250 MB (с OOM-loop) | 307 MB available |
|
||
| Dropbear процессов | 21 | 2 (listener + моя сессия) |
|
||
| Outbound SMTP-соединений | 30+ | 0 |
|
||
| Counter `incident_block_in 22` | — | растёт (атакующие тыкаются) |
|
||
|
||
## Постоянные правила (`/etc/nftables.d/99-incident-20260520.nft`)
|
||
|
||
```nft
|
||
chain incident_block_in {
|
||
type filter hook input priority -100; policy accept;
|
||
iifname "eth0" tcp dport 22 counter drop comment "incident-20260520-no-ssh-from-wan"
|
||
}
|
||
chain incident_block_out {
|
||
type filter hook output priority -100; policy accept;
|
||
oifname "eth0" tcp dport { 25, 465, 587, 2375 } counter drop comment "incident-20260520-block-spam"
|
||
oifname "eth0" tcp dport 22 counter drop comment "incident-20260520-block-ssh-brute"
|
||
}
|
||
chain incident_block_fwd {
|
||
type filter hook forward priority -100; policy accept;
|
||
oifname "eth0" tcp dport { 25, 465, 587, 2375 } counter drop comment "incident-20260520-block-spam"
|
||
oifname "eth0" tcp dport 22 counter drop comment "incident-20260520-block-ssh-brute"
|
||
}
|
||
```
|
||
|
||
SSH доступ остался только через:
|
||
- LAN (`192.168.1.0/24`, `br-lan`)
|
||
- NetBird (`100.70.207.97`, `wt0`)
|
||
|
||
## Расширение масштаба: Unifi + NetBird-mesh
|
||
|
||
Бенелюкс — **не изолированный объект**. Cudy за время взлома имел два открытых вектора в чужие сети:
|
||
|
||
1. **LAN Бенелюкса (192.168.1.0/24)** — здесь живёт **Unifi-сегмент**: 3 AP/Switch (`70:a7:41:79:ef:29`, `70:a7:41:9a:9e:92`, `70:a7:41:c1:33:0a`). Атакующие, сидя на Cudy под root, имели L2 ко всей подсети — могли сниффить broadcasts, ARP, DHCP. К какому контроллеру эти устройства adopted — на момент расследования не выяснено: inform-трафика ни к LXC 116 НИИКН (`100.70.138.234`), ни к UDM-Pro Знаменского нет. Одно из устройств (`192.168.1.199`, hostname `Benelyuks`) стучится в `192.168.28.34:8381` — это IP не из NetBird, пакеты уходят в default-шлюз провайдера без ответа. Похоже на orphaned-сегмент, см. [[projects/benilux/README#unifi-сегмент-за-cudy]].
|
||
|
||
2. **NetBird-mesh через wt0** — Cudy получает по NetBird маршруты в:
|
||
- `10.0.0.0/24` (через openclaw — это вся домашняя dttb-инфра)
|
||
- `10.253.1.0/24` + `2.63.246.0/24` + `87.250.251.0/24` + `95.167.245.0/24` (через pve-LionART — ММФБ)
|
||
- `192.168.1.0/24` (через pve-niikn — НИИКН; конфликт с локальной подсетью)
|
||
- `192.168.2.0/24` (Переделки), `192.168.8.0/24`, `192.168.88.0/24`
|
||
|
||
Атакующие, имея root на Cudy с активным NetBird agent, теоретически могли достучаться до любого хоста в этих сетях. На практике для этого надо знать топологию (которой у них не было) и проводить активную разведку (не видно в коротких SMTP-сессиях). Но риск ненулевой — особенно для **LXC 116 unifi-controller** (`100.70.138.234:8443`) и **Proxmox НИИКН** (`pve-niikn 100.70.120.229`), которые видны напрямую.
|
||
|
||
**Что проверить отдельно** (не в этом фиксе):
|
||
- Логи Docker LXC 116 unifi-controller (на pve-niikn, `/opt/unifi/config/logs/`) на попытки входа / сессии с `100.70.207.97` за 2026-05-20 13:00–15:45 MSK
|
||
- NetBird access policy для группы `OpenWRT VPN` — какие пиры/подсети разрешены этой группе
|
||
|
||
## Что НЕ сделано (на твоё решение)
|
||
|
||
1. **Полный wipe / sysupgrade -n.** Малварь была memory-resident (`/tmp/.2424` уже не существовало), бэкдоров на диске не найдено (find -mtime -7 чист в `/etc /lib /sbin /usr/sbin /opt`). Но 100% гарантии чистоты после взлома `root` без переустановки нет. Рекомендую перезалить роутер в течение недели в окно даунтайма.
|
||
2. **Жёсткое ограничение dropbear на интерфейсы.** Сейчас он слушает на всех (`0.0.0.0:22`), правило отбрасывает только `iifname eth0`. Можно дополнительно через `uci set dropbear.@dropbear[0].Interface=lan` ограничить bind. Не делал — риск разрыва.
|
||
3. **Audit прочих хостов с тем же паролем.** `1qaz!QAZ` фигурирует в инфраструктуре много где (Proxmox, Gitea-WebUI, NPM, Nextcloud, openclaw-LXC, server1c, MikroTik и др.). Также UDM-Pro использует похожий `1qaz!QAZ!QAZ`. **Если хоть один публично-доступный хост с этим паролем существует — он тоже скомпрометирован.** Нужен аудит.
|
||
4. **Уведомление abuse.** `45.143.21.60` рассылал спам несколько часов (минимум) — стоит ожидать blocklist-листинги (Spamhaus CSS/XBL, abuseipdb).
|
||
5. **Чистка `/var/log/dropbear`** (если есть) — для удаления fingerprint атакующих, но это удалит и улики.
|
||
|
||
## SMTP forward разблокирован (2026-05-20 ~17:00 MSK)
|
||
|
||
Александр пожаловался что почта перестала работать — это побочный эффект моего forward-drop для 25/465/587. Снял **forward** chain для этих портов (`/etc/nftables.d/99-incident-20260520.nft`), оставил только output-drop (с самого роутера — там SMTP-клиента быть не должно) + forward-drop для 22 (защита от LAN→WAN SSH-брута, если в сети окажется скомпрометированное устройство). Apple Mail/Outlook у LAN-клиентов снова работает.
|
||
|
||
## Постоянный фикс (2026-05-20 16:30 MSK)
|
||
|
||
После исходной изоляции выявлено в UCI: `firewall.@rule[9].name='Allow-SSH-WAN'` — **корневая причина инцидента**, явное разрешение SSH с интернета. Также включён парольный auth: `dropbear.main.PasswordAuth=on`, `RootPasswordAuth=on`. Применено:
|
||
|
||
```
|
||
# backup
|
||
cp /etc/config/firewall /etc/config/firewall.bak.incident-20260520
|
||
cp /etc/config/dropbear /etc/config/dropbear.bak.incident-20260520
|
||
cp /etc/dropbear/authorized_keys /etc/dropbear/authorized_keys.bak.incident-20260520
|
||
|
||
# второй ключ в authorized_keys (recovery, если Mac отвалится)
|
||
cat >> /etc/dropbear/authorized_keys <<'KEY'
|
||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKlYObrWNTPQbR+WXMURscQ85Xc5HTLZa+wC8sf8WU72 claude-code@code-server
|
||
KEY
|
||
|
||
# удалить дырявые UCI-правила
|
||
uci delete firewall.@rule[<idx>] # Allow-SSH-WAN
|
||
uci delete firewall.@rule[<idx>] # Allow-IPSec-ESP
|
||
uci delete firewall.@rule[<idx>] # Allow-ISAKMP
|
||
|
||
# key-only
|
||
uci set dropbear.main.PasswordAuth='off'
|
||
uci set dropbear.main.RootPasswordAuth='off'
|
||
|
||
uci commit firewall && uci commit dropbear
|
||
fw4 reload && /etc/init.d/dropbear restart
|
||
```
|
||
|
||
**Verify:** вход по ключу — ОК; вход по паролю — `Permission denied (publickey)` (dropbear даже password-prompt не показывает).
|
||
|
||
## NetBird route — NIIKN остаётся в mesh (2026-05-20 16:50 MSK)
|
||
|
||
Изначально планировалось убрать route `192.168.1.0/24` от pve-niikn для устранения конфликта. По решению Олега — NIIKN-route в mesh нужен, оставлен (новый id после re-create: `d86ug0rl0ubs73djq120`, peer `cqrj61bl0ubs73dkhq70` pve-niikn).
|
||
|
||
Сейчас тот же `192.168.1.0/24` анонсируют два пира:
|
||
- `d86ug0rl0ubs73djq120` — peer **pve-niikn**, network_id="NIIKN"
|
||
- `d7kkgtbl0ubs73du6560` — peer **nbgw-glavtorg**, network_id="Glavtorg-LAN"
|
||
|
||
Какой именно будет выбран на каждом client-peer — определяется NetBird's внутренней логикой metric/peer-status. Для надёжной работы по конкретному объекту с конфликтующим /24 — ходи по NetBird-IP пира, не по LAN-IP (для Бенелюкса: `100.70.207.97`, для LXC 116 unifi-controller: `100.70.138.234`).
|
||
|
||
## Улики
|
||
|
||
Локально на mac: `/tmp/benelux-evidence/`
|
||
- `recon.txt` — ps/netstat/dmesg/cron на момент обнаружения
|
||
- `lockdown.txt` — лог изоляции (kill 19 сессий)
|
||
- `harden.txt` — установка ключа, чистка cron
|
||
- `new_password.txt` (chmod 600) — новый root пароль
|
||
- `recon.sh`, `lockdown.sh`, `harden.sh`, `finalize.sh` — исполненные скрипты
|
||
|
||
## Open questions для Олега
|
||
|
||
- [ ] Audit паролей на других хостах (особенно публично-доступных) — выше
|
||
- [ ] Когда планируем wipe+sysupgrade Бенелюкса?
|
||
- [ ] Сообщить ли Александру (клиент в КП Бенелюкс) — на объекте только podkop для обхода блокировок, бизнес-сервисов нет, утечки клиентских данных не было; вопрос косметический
|
||
- [ ] Кто сделал WAN-SSH публичным изначально? (по умолчанию OpenWrt блокирует ssh на wan)
|