# ECLIPSE ATTACK НА СЕТЬ MONTANA - ДЕТАЛЬНЫЙ АНАЛИЗ **Модель:** Grok 3 **Компания:** xAI **Дата:** 07.01.2026 17:00 UTC ## ВВЕДЕНИЕ Проведен детальный анализ сетевого слоя Montana на предмет возможности Eclipse Attack согласно шаблону из `PROMPT_COUNSIL_TEMPLATE.md`. Анализ включает проверку всех трех критических аспектов: netgroup diversity для outbound, anchor connections, и bucket collision handling. ## КРИТИЧЕСКАЯ НАХОДКА: ECLIPSE ATTACK ВОЗМОЖЕН **Статус:** 🔴 **КРИТИЧЕСКАЯ УЯЗВИМОСТЬ - ECLIPSE ATTACK РЕАЛИЗУЕМ** ## АНАЛИЗ КОДА ### 1. ANCHOR CONNECTIONS - ОТСУТСТВУЮТ **Файл:** `protocol.rs`, строка 206 ```rust // NOTE: Montana does NOT use anchor connections (see Network struct comment). ``` **Анализ:** - ❌ **НЕТ механизма anchor connections** между рестартами - ❌ После рестарта все адреса загружаются из `addresses.dat` без приоритизации - ❌ Нет "trusted" адресов, которые гарантированно сохраняются между рестартами - ❌ Нет механизма сохранения надежных outbound соединений **Уязвимость:** После рестарта жертвы все outbound соединения выбираются из AddrMan без гарантии, что они не контролируются атакующим. ### 2. NETGROUP DIVERSITY - НЕДОСТАТОЧНА ДЛЯ OUTBOUND **Файлы:** `connection.rs`, `protocol.rs`, `addrman.rs` **Анализ кода:** ```517:519:Montana ACP/montana/src/net/protocol.rs // Check netgroup diversity if !connections.can_connect(&socket_addr).await { continue; ``` ```264:270:Montana ACP/montana/src/net/connection.rs /// Check if we can connect to this address (netgroup diversity) pub async fn can_connect(&self, addr: &SocketAddr) -> bool { let netgroup = get_netgroup(addr); let counts = self.netgroup_counts.lock().await; let current = counts.get(&netgroup).copied().unwrap_or(0); current < MAX_PEERS_PER_NETGROUP ``` **Проблема:** - ✅ Netgroup diversity проверяется **ПОСЛЕ** выбора адреса из AddrMan - ❌ `select()` в AddrMan **НЕ гарантирует** выбор из разных netgroups - ❌ `select_from_new()` и `select_from_tried()` используют случайный bucket выбор - ❌ Если NEW table заполнена адресами из 4-х /16 подсетей атакующего, все 8 outbound могут быть из этих подсетей **Уязвимость:** MAX_PEERS_PER_NETGROUP=2 защищает только от превышения лимита, но не гарантирует разнообразие при выборе адресов. ### 3. BUCKET COLLISION HANDLING - УЯЗВИМОСТЬ **Файл:** `addrman.rs`, строки 201-208 ```201:208:Montana ACP/montana/src/net/addrman.rs // Handle collision if let Some(existing_idx) = self.tried_table[idx] { // Move existing back to new self.move_to_new(existing_idx); } self.tried_table[idx] = Some(addr_idx); self.tried_count += 1; ``` **Анализ:** - При `mark_good()` если bucket занят, старый адрес перемещается обратно в NEW table - Атакующий может использовать это для: 1. Вытеснения легитимных адресов из TRIED table 2. Заполнения TRIED table своими адресами через повторные `mark_good()` вызовы **Уязвимость:** Коллизии в TRIED table могут быть использованы для вытеснения легитимных адресов. ### 4. ЗАПОЛНЕНИЕ NEW TABLE - БЕЗ ЗАЩИТЫ **Файл:** `addrman.rs`, строки 408-416 ```408:416:Montana ACP/montana/src/net/addrman.rs /// Add multiple addresses (from addr message) pub fn add_many(&mut self, addrs: Vec, source: SocketAddr) -> usize { let mut added = 0; for addr in addrs { if self.add(addr, Some(source)) { added += 1; } } added } ``` **Анализ:** - ❌ Нет rate limiting на `add_many()` - ❌ Нет проверки разнообразия netgroups при добавлении - ❌ Атакующий может отправить 1000 адресов за раз (MAX_ADDR_SIZE) - ❌ NEW table: 1024 buckets × 64 slots = 65,536 возможных адресов **Уязвимость:** Атакующий может заполнить NEW table вредоносными адресами через множественные Addr сообщения. ### 5. ВЫБОР АДРЕСОВ - СЛУЧАЙНЫЙ, БЕЗ ГАРАНТИЙ **Файл:** `addrman.rs`, строки 230-245 ```230:245:Montana ACP/montana/src/net/addrman.rs fn select_inner(&mut self, new_only: bool) -> Option { let mut rng = ChaCha20Rng::from_entropy(); // 50% chance to try new address (or 100% if new_only) let use_new = new_only || rng.gen_bool(0.5); if use_new && self.new_count > 0 { self.select_from_new(&mut rng) } else if self.tried_count > 0 { self.select_from_tried(&mut rng) } else if self.new_count > 0 { self.select_from_new(&mut rng) } else { None } } ``` **Проблема:** - `select_from_new()` и `select_from_tried()` используют случайный выбор bucket - Нет гарантии выбора из разных netgroups - Если NEW table заполнена адресами атакующего, вероятность выбора легитимного адреса низка ## ЭКСПЛУАТАЦИЯ ECLIPSE ATTACK ### ФАЗА 1: ЗАПОЛНЕНИЕ NEW TABLE **Цель:** Заполнить NEW table вредоносными адресами **Шаги:** 1. Подключиться к жертве как inbound peer 2. Отправить множественные `Addr` сообщения с вредоносными адресами: - До 1000 адресов за сообщение (MAX_ADDR_SIZE) - Использовать разные /16 подсети (минимум 4 для обхода MAX_PEERS_PER_NETGROUP=2) - Каждый адрес должен быть routable (не private/loopback) 3. Повторить с разных IP адресов для обхода rate limiting 4. Цель: заполнить как можно больше buckets в NEW table **Код эксплуатации:** ```rust // Создать 65k+ вредоносных адресов в разных /16 подсетях let mut malicious_addrs = Vec::new(); for subnet in 0..4 { // 4 разные /16 подсети for i in 0..16384 { // 16k адресов на подсеть let ip = Ipv4Addr::new( subnet as u8, (i / 256) as u8, (i % 256) as u8, 1 ); malicious_addrs.push(NetAddress::new( IpAddr::V4(ip), 19333, NODE_FULL )); } } // Отправить через Addr сообщения (по 1000 за раз) for chunk in malicious_addrs.chunks(1000) { send_addr_message(chunk.to_vec()); } ``` ### ФАЗА 2: ПРОДВИЖЕНИЕ В TRIED TABLE **Цель:** Переместить вредоносные адреса из NEW в TRIED table **Шаги:** 1. Установить 8 outbound соединений от жертвы к атакующим адресам 2. Для каждого соединения: - Успешно завершить handshake - Поддерживать соединение активным - Отправлять полезные сообщения (slices, transactions) 3. Жертва вызывает `mark_connected()` → `mark_good()` для каждого соединения 4. Адреса перемещаются из NEW в TRIED table **Проблема с bucket collisions:** - Если bucket в TRIED table занят легитимным адресом, он перемещается обратно в NEW - Атакующий может повторно вызывать `mark_good()` для вытеснения легитимных адресов ### ФАЗА 3: ОЖИДАНИЕ РЕСТАРТА **Цель:** Дождаться рестарта жертвы **Шаги:** 1. Поддерживать вредоносные соединения активными 2. Мониторить жертву на предмет рестарта 3. После рестарта: - AddrMan загружается из `addresses.dat` - Все адреса в TRIED table сохраняются - Anchor connections отсутствуют ### ФАЗА 4: ECLIPSE УСПЕШЕН **Результат:** 1. После рестарта жертва выбирает outbound адреса из AddrMan 2. Все 8 outbound соединений идут к атакующему (из TRIED table) 3. Жертва изолирована в контролируемой сети атакующего 4. Атакующий может: - Блокировать транзакции - Предоставлять ложную информацию о chain state - Проводить double-spend атаки - Манипулировать consensus ## ПРОВЕРКА ЧЕКЛИСТА Согласно шаблону: ``` [ ] Eclipse: netgroup diversity работает ❌ НЕ РАБОТАЕТ для outbound выбора [ ] Eclipse: anchor connections есть ❌ ОТСУТСТВУЮТ [ ] Eclipse: bucket collision handling ⚠️ УЯЗВИМО ``` ## МИТИГАЦИИ И РЕКОМЕНДАЦИИ ### КРИТИЧЕСКИЕ ИСПРАВЛЕНИЯ: 1. **Добавить Anchor Connections:** - Сохранять 2-3 надежных outbound соединения между рестартами - Приоритизировать эти адреса при выборе - Использовать отдельную таблицу для anchor адресов 2. **Улучшить Netgroup Diversity для Outbound:** - Гарантировать выбор из разных netgroups при `select()` - Требовать минимум 4 разных /16 подсети для 8 outbound соединений - Проверять diversity ДО выбора адреса, а не после 3. **Защита от Bucket Collision Abuse:** - Ограничить частоту `mark_good()` вызовов - Защищать старые адреса в TRIED table от вытеснения - Использовать более сложную логику для collision handling 4. **Rate Limiting для Addr Messages:** - Ограничить количество адресов, принимаемых от одного peer - Проверять разнообразие netgroups при добавлении - Требовать подтверждение адресов перед добавлением в TRIED ## ЗАКЛЮЧЕНИЕ **Eclipse Attack на сеть Montana РЕАЛИЗУЕМ** из-за: 1. Отсутствия anchor connections 2. Недостаточной netgroup diversity при выборе outbound адресов 3. Возможности заполнения NEW table вредоносными адресами 4. Уязвимости bucket collision handling в TRIED table **Критичность:** 🔴 **КРИТИЧЕСКАЯ** **Вероятность успешной атаки:** ВЫСОКАЯ при наличии достаточных ресурсов (4+ /16 подсетей, множественные IP адреса) **Время до эксплуатации:** Среднее (требует времени на заполнение таблиц и ожидание рестарта)