**Модель:** Gemini 3 Pro **Компания:** Google **Дата:** 07.01.2026 14:50 UTC --- # TIER 0: КРИТИЧЕСКИЕ ## 1. Eclipse Attack: Отравление AddrMan и отсутствие Anchor Connections **Файлы:** `montana/src/net/addrman.rs`, `montana/src/net/connection.rs`, `montana/src/net/protocol.rs` ### Анализ кода 1. **Уязвимость вытеснения из Tried Table (`addrman.rs`):** В методе `mark_good` (строка 181) при коллизии в таблице проверенных адресов (`tried_table`) вызывается `move_to_new` (строка 207). ```rust // Handle collision if let Some(existing_idx) = self.tried_table[idx] { // Move existing back to new self.move_to_new(existing_idx); } ``` Это классическая уязвимость. Атакующий может намеренно создавать коллизии в бакетах (зная алгоритм SipHash и ключ или методом перебора), заставляя узел перемещать "хорошие" легитимные адреса обратно в таблицу `new_table`, где они могут быть удалены или затеряться среди адресов атакующего. 2. **Отсутствие Anchor Connections (`protocol.rs`, `connection.rs`):** В `protocol.rs` (строки 206-207) явно указано: ```rust // NOTE: Montana does NOT use anchor connections (see Network struct comment). ``` В Bitcoin Core файл `anchors.dat` сохраняет активные исходящие соединения при выключении и пробует подключиться к ним *первыми* при старте. В Montana этого нет. При рестарте узел полностью полагается на содержимое `addrman` (`addresses.dat`). Если `tried_table` была отравлена (см. п.1), узел подключится только к узлам атакующего. 3. **Слабая диверсификация исходящих (`protocol.rs`):** Цикл `connection_loop` (строки 467-605) использует `addrman.select()` для выбора пиров. Хотя `addrman` пытается выбирать из разных бакетов, если *большинство* бакетов в `tried_table` контролируется атакующим (из-за уязвимости п.1), проверка `/16` netgroup не поможет, если атакующий имеет IP в разных подсетях (или использует ботнет). ### Эксплуатация (Chain of Exploitation) 1. **Заполнение (Filling):** Атакующий отправляет жертве тысячи `Addr` сообщений с подконтрольными IP-адресами, заполняя `new_table`. 2. **Продвижение (Promotion):** Атакующий устанавливает входящие соединения с жертвой с этих IP. Жертва, видя активность, может (в зависимости от логики) попытаться соединиться в ответ или просто обновить timestamp. При успешном исходящем соединении адрес попадает в `tried_table`. 3. **Вымывание (Eviction):** Атакующий продолжает добавлять новые "свои" адреса, вызывая коллизии в `tried_table`. Из-за логики `move_to_new`, старые честные пиры вылетают в `new_table`. 4. **Изоляция (Eclipse):** Атакующий ждет перезапуска узла жертвы (или провоцирует его DoS-атакой). 5. **Захват:** После рестарта жертва загружает `addresses.dat` (где `tried_table` отравлена) и не имеет `anchors.dat`. Все 8 исходящих соединений устанавливаются с узлами атакующего. ### Рекомендации по исправлению 1. **Исправить коллизии в Tried:** Вместо `move_to_new`, тестировать новый адрес. Если он работает, а старый нет — заменять. Если оба работают — оставлять старый (принцип "первый пришел — занял место"). 2. **Внедрить Anchors:** Создать `anchors.dat`, сохраняющий 2-4 проверенных пира при выключении. При старте пробовать их в первую очередь. 3. **Outbound Eviction:** Внедрить защиту от Eclipse для исходящих соединений (мониторинг качества цепи, сравнение заголовков с другими пирами, Feeler connections для проверки новых адресов).