montana/Русский/Совет/OpenAI/атака_затмения_07.01.2026_18:11.md

91 lines
8.3 KiB
Markdown
Raw Permalink 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.

**Модель:** GPT-5.2
**Компания:** OpenAI
**Дата:** 07.01.2026 18:11 UTC
## Задача
Найти практический вектор **Eclipse Attack** на сеть Montana (P2P), опираясь на код в `/Montana ACP/montana/src/net/`.
## TL;DR (главная уязвимость)
Заявленная защита “full bootstrap verification (100 peers, 25+ /16 subnets, hardcoded median check)” **фактически не исполняется** в текущей реализации:
- `main.rs` только **логирует** «Startup verification … Full bootstrap…», но **не вызывает** `StartupVerifier` / `BootstrapVerifier`.
- `Network::start()` запускает listener/connector/maintenance и сразу добавляет user-supplied `seeds` в `AddrMan`, после чего `connection_loop` начинает диалить адреса **без какого-либо гейта “verification passed”**.
- `net/startup.rs` содержит заглушку `query_hardcoded_tips()``Vec::new()`, то есть даже если verifier вызывать, он **не сможет** набрать `MIN_HARDCODED_RESPONSES`.
Следствие: Eclipse сводится к классике — **poisoning AddrMan + перехват outbound**.
## Доказательства по коду (ключевые места)
### 1) Startup verification не выполняется
`montana/src/main.rs`:
- Есть лог о “Startup verification … Full bootstrap…”, но дальше код сразу делает `Network::new()` и `network.start()` (без вызова verifier).
`montana/src/net/protocol.rs`:
- `Network::start()` спаунит `listener_loop`, `connection_loop`, `maintenance_loop`, затем добавляет `seeds` через `add_seed()` и возвращает `Ok(())`.
- Никакой проверки, что “startup verification passed”, нет.
### 2) StartupVerifier — заглушка
`montana/src/net/startup.rs`:
- `query_hardcoded_tips()` возвращает `Vec::new()` (placeholder), а `total_peers` в результате = `responses.len()` с комментарием “Would be 100 in full implementation”.
### 3) Addr poisoning реально влияет на выбор outbound
`montana/src/net/protocol.rs`:
- `connection_loop` выбирает адрес через `addrman.select()` (50/50 NEW vs TRIED) и затем коннектится.
### 4) TRIED заполняется после handshake (это хорошо), но это делает eclipse ещё проще при отсутствии bootstrapping
`montana/src/net/protocol.rs`:
- На `Message::Verack` вызывается `addresses.write().await.mark_connected(&peer.addr);` — перевод адреса в TRIED происходит после успешного handshake.
### 5) Addr rate-limit легко обходится Sybilом (лимит per-connection)
`montana/src/net/rate_limit.rs`:
- `AddrRateLimiter`: **burst 1000**, sustained **0.1 addr/sec**.
- Лимитер хранится в `Peer` → лимит **на соединение**, а не глобальный.
- Значит атакующий открывает много соединений (входящих/исходящих) и с каждого отправляет по 1000 адресов → быстро забивает NEW таблицу.
## Практическая схема Eclipse Attack (эксплуатация)
### Предпосылки
- Жертва запускает узел и имеет хотя бы 12 канала к атакующему (например, через `--seeds` или просто подключившись к атакующему узлу).
- Атакующий контролирует набор IPов, желательно распределённых по разным /16 (или IPv6-префиксам так, как считает `get_netgroup`).
### Шаг 1 — “засорить NEW” адресной книгой атакующего
1) Атакующий устанавливает соединение с жертвой и доводит handshake до `Verack` (иначе нельзя слать `Addr`).
2) Сразу после handshake отправляет `Addr` с максимумом адресов (до 1000 в сообщении).
3) Повторяет через множество Sybil-соединений: каждый `Peer` имеет свой `AddrRateLimiter` → снова 1000 burst.
Результат: `AddrMan::new_table` (1024 buckets × 64) — до ~65k слотов — может быть существенно заполнена адресами атакующего.
### Шаг 2 — перевести атакующие адреса в TRIED
1) Т.к. `connection_loop` выбирает адреса из AddrMan (50/50 NEW/TRIED) и **нет гейта на bootstrap-verification**, жертва начнёт диалить адреса из отравленного AddrMan.
2) Атакующие узлы принимают соединение и корректно отвечают handshake.
3) На `Verack` адрес переводится в `TRIED` (`mark_connected`).
Результат: со временем TRIED (256×64 = 16384 слота) тоже становится “атакующий-доминант”.
### Шаг 3 — рестарт жертвы и «полный eclipse»
После рестарта жертва снова будет выбирать peers из AddrMan (частично TRIED) и практически все outbound уйдут на атакующего.
### Ограничения и как атакующий их обходит
- **MAX_OUTBOUND = 8**, **MAX_PEERS_PER_NETGROUP = 2** (т.е. максимум 2 исходящих на один /16).
- Для полного перехвата 8 outbound нужно иметь ≥4 разных netgroup (/16) и по 2 адреса в каждом.
- **MAX_CONNECTIONS_PER_IP = 2** — не даёт одному IP занять много слотов.
- Но атакующий использует несколько IP.
- Факт отсутствия “100 peers / 25+ subnets / hardcoded median check” делает стоимость атаки **на порядки ниже**, чем заявлено в комментариях.
## Почему это именно Eclipse (а не просто Sybil)
Потому что цель — **монополизировать видимость сети жертвы** за счёт контроля всех/почти всех outbound + доминирования адресной книги, а не просто “иметь много узлов”. Здесь это достигается через AddrMan poisoning и отсутствие обязательной startup-верификации.
## Рекомендации (high level)
1) **Сделать startup verification реальным гейтом**:
- до запуска `connection_loop` собрать 100 ответов, проверить 25+ /16, проверить hardcoded-median, и только затем разрешать outbound.
2) **Убрать/жёстко ограничить доверие к `--seeds`**:
- сейчас `add_seed()` bypassит часть проверок и фактически даёт атакующему якорь.
3) **Глобальный и per-IP/per-netgroup лимит на Addr ingestion**:
- текущий лимит per-peer легко обходится множеством соединений.
4) (Если включать feelers) **Feeler должен проходить protocol handshake**, иначе “TCP-only reachability” снова откроет прямой путь к TRIED poisoning.
---
## Приложение: ключевые файлы
- `montana/src/net/protocol.rs` — выбор outbound (`AddrMan::select`), обработка `Addr`, перевод в `TRIED` на `Verack`.
- `montana/src/net/addrman.rs` — NEW/TRIED таблицы, bucket logic.
- `montana/src/net/startup.rs` и `montana/src/net/bootstrap.rs` — заявленная модель защиты, но сейчас не интегрирована/частично заглушена.
- `montana/src/net/rate_limit.rs` — per-peer токенбакеты.