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

12 KiB
Raw Blame History

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

// 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

Анализ кода:

// Check netgroup diversity
if !connections.can_connect(&socket_addr).await {
    continue;
/// 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

// 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

/// Add multiple addresses (from addr message)
pub fn add_many(&mut self, addrs: Vec<NetAddress>, 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

fn select_inner(&mut self, new_only: bool) -> Option<NetAddress> {
    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

Код эксплуатации:

// Создать 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 адреса)

Время до эксплуатации: Среднее (требует времени на заполнение таблиц и ожидание рестарта)