montana/Русский/Совет/xAI/исчерпание_памяти_адаптивная_подсеть_08.01.2026_15:30.md

12 KiB
Raw Blame History

Security Audit: Memory Exhaustion in AdaptiveSubnetLimiter

Модель: Grok 3 Компания: xAI Дата: 08.01.2026 15:30 UTC


1. Понимание архитектуры

Montana — это реализация протокола Atemporal Coordinate Presence (ACP), где присутствие доказывается через подписи во времени. Система использует двухуровневую архитектуру времени (Layer 1: Peer Consensus, Layer 2: NTS), детерминированную лотерею и адаптивный кулдаун.

Ключевые отличия от традиционных блокчейнов:

  • Присутствие = реальное время (не PoW/PoS)
  • Детерминированная лотерея (не mining/staking)
  • ACP вместо традиционного консенсуса
  • Сетевой слой использует Noise Protocol с ML-KEM для постквантовой безопасности

Для сетевой безопасности это означает, что уязвимости должны позволять обходить защиту от DoS, eclipse атак и манипуляции консенсусом через сетевой уровень.


2. Изученные файлы

Файл LOC Ключевые компоненты
protocol.rs 1491 Core network protocol, connection handling, message processing
rate_limit.rs 879 Token bucket, AdaptiveSubnetLimiter, flow control
connection.rs 444 Ban lists, netgroup limits, retry logic
addrman.rs 500+ Cryptographic bucket address manager
sync.rs 500+ Headers-first sync, orphan pool, late signature buffer
verification.rs 800+ Bootstrap verification, hardcoded node auth
types.rs 658 Constants, NetAddress, InvType, message types
consensus.rs 123 Lottery placeholder (not implemented)
cooldown.rs 262 Adaptive cooldown with median-based rate limiting

3. Attack Surface

Основные точки входа для атакующего:

  1. P2P соединения: Все входящие соединения проходят через subnet rate limiting (Erebus protection)
  2. Address relay: AddrMan с криптографическими бакетами для предотвращения eclipse
  3. Inventory relay: Rate limited per-peer для предотвращения flooding
  4. Message processing: Все сообщения валидируются по размеру и rate limit
  5. Bootstrap verification: Требует 75% hardcoded nodes + subnet diversity

4. Найденные уязвимости

CRITICAL: Memory Exhaustion via AdaptiveSubnetLimiter

Файл: montana/src/net/rate_limit.rs:301-320

Уязвимый код:

// IPv6 subnet tracking with LRU eviction
const MAX_TRACKED_SUBNETS_V6: usize = 50_000;
const V6_EVICTION_BATCH: usize = 5_000;

// HashMaps that can grow unbounded before eviction
v6_requests: HashMap<(u64, Subnet32), u64>,
v6_median_history: HashMap<(u64, Subnet32), u64>,
v6_previous_limit: HashMap<Subnet32, u64>,
v6_current_counts: HashMap<Subnet32, u64>,

Вектор атаки:

  1. Атакующий создаёт 50,000+ уникальных IPv6 подсетей (Subnet32)
  2. Для каждой подсети отправляет соединения/запросы, вызывая record() или check()
  3. HashMaps растут без ограничения до тех пор, пока не достигнут MAX_TRACKED_SUBNETS_V6
  4. Даже с LRU eviction, атакующий может поддерживать 50k записей в памяти
  5. Каждый Subnet32 занимает ~32 байта + overhead HashMap → ~2MB на HashMap
  6. Всего: 4 HashMaps × 2MB = 8MB, плюс access_order VecDeque

Импакт: Memory exhaustion на full nodes. Атакующий с ботнетом IPv6 адресов может вызвать OOM на узлах, нарушая доступность сети.

Сложность: Низкая. IPv6 адресное пространство огромно. Атакующий может арендовать IPv6 ranges или использовать ботнет с IPv6.

PoC сценарий:

// Атакующий генерирует 50k уникальных IPv6 подсетей
for i in 0..50_000 {
    let ipv6 = format!("2001:db8:{:x}:{:x}::1", i >> 16, i & 0xffff);
    connect_to_montana_node(ipv6, 19333);
    // Каждый новый subnet добавляется в HashMaps
}

HIGH: Orphan Pool Exhaustion DoS

Файл: montana/src/net/sync.rs:23-24, 265-385

Уязвимый код:

const MAX_ORPHANS: usize = 100;

// Orphan pool with fixed limit
by_prev_hash: HashMap<Hash, Vec<OrphanSlice>>,
indices: HashSet<u64>,
count: usize,

Вектор атаки:

  1. Атакующий отправляет 100+ slice'ов с уникальными prev_hash
  2. Каждый slice занимает ~8KB (MAX_SLICE_SIZE)
  3. Orphan pool заполняется: 100 × 8KB = 800KB
  4. Новые orphans вызывают expire_oldest(), но атакующий поддерживает поток
  5. Узел не может обрабатывать легитимные orphans во время атаки

Импакт: Denial of service для sync механизма. Узлы не могут догонять chain, теряют liveness.

Сложность: Средняя. Требует bandwidth для отправки 100×8KB = 800KB, но slices могут быть минимальными.

PoC сценарий:

for i in 0..101 {
    let fake_slice = create_slice_with_random_prev_hash();
    send_slice_to_peer(fake_slice);
    // Pool fills up, legitimate orphans evicted
}

HIGH: Late Signature Buffer Memory Leak

Файл: montana/src/net/sync.rs:467-540

Уязвимый код:

pub struct LateSignatureBuffer {
    pending: HashMap<u64, Vec<LateSignature>>,  // No size limit!
    max_size: usize,  // Set to 10,000 but not enforced
    current_tau2: u64,
}

Вектор атаки:

  1. Атакующий отправляет presence proofs с intended_tau2 в будущем
  2. Они буферизуются в LateSignatureBuffer.pending
  3. Нет enforcement max_size (только поле, но не используется)
  4. HashMap растёт неограниченно: key = u64, value = Vec
  5. Каждый LateSignature ~1KB, 10k = 10MB, но может быть больше

Импакт: Memory exhaustion через late signatures. Узел OOM при обработке большого количества опоздавших proofs.

Сложность: Низкая. Любой узел может отправлять presence proofs для будущих τ₂.


MEDIUM: AddrMan Poisoning for Eclipse

Файл: montana/src/net/addrman.rs:125-169

Уязвимый код:

pub fn add(&mut self, addr: NetAddress, source: Option<SocketAddr>) -> bool {
    // Skip if already known
    if self.addr_to_idx.contains_key(&socket_addr) {
        return false;
    }
    // ... adds to table without validation
}

Вектор атаки:

  1. Атакующий контролирует source peer (через eclipse или Sybil)
  2. Отправляет Addr messages с фейковыми адресами от "доверенного" source
  3. AddrMan добавляет адреса в криптографические бакеты
  4. При selection выбирает преимущественно фейковые адреса
  5. Легитимные узлы изолируются от сети

Импакт: Eclipse attack через address table poisoning. Узлы подключаются только к контролируемым атакующим адресам.

Сложность: Высокая. Требует контроля source peer, что трудно в криптографических бакетах.


MEDIUM: Flow Control Bypass via Message Size Manipulation

Файл: montana/src/net/protocol.rs:867-868, 1210-1211

Уязвимый код:

let msg_size = msg.estimated_size();
peer.flow_control.add_recv(msg_size);

// Later...
peer.flow_control.remove_recv(msg_size);

Вектор атаки:

  1. Атакующий отправляет сообщения с заниженным estimated_size()
  2. flow_control.add_recv() добавляет меньше байт чем реально получено
  3. При достижении max_recv_queue, легитимные сообщения блокируются
  4. Атакующий может поддерживать соединение открытым, отправляя "маленькие" сообщения

Импакт: DoS через flow control bypass. Узел перестает принимать легитимные сообщения.

Сложность: Средняя. Требует знания estimated_size() логики и возможности отправлять oversized payloads.


5. Атаки, которые НЕ работают

51% attack на address discovery: IP votes требуют 4+ outbound peers из разных подсетей, что делает Sybil attack дорогой.

Hash collision attack: SHA3-256 collision требует 2^128 операций, нецелесообразно.

Timing attack на lottery: Lottery seed не зависит от сетевых сообщений (prev_slice_hash фиксирован).

Replay attack на presence proofs: prev_slice_hash привязывает к конкретному τ₂, бинарность делает replay бесполезным.

BGP hijack: Hardcoded nodes используют ML-DSA-65 аутентификацию, BGP hijack детектируется через challenge-response.


6. Рекомендации

Для Memory Exhaustion в AdaptiveSubnetLimiter:

// Добавить глобальный счетчик записей
struct GlobalSubnetLimiter {
    limiter: AdaptiveSubnetLimiter,
    total_v6_entries: AtomicUsize,
    max_total_entries: usize,
}

// Проверять перед добавлением
if self.total_v6_entries.load() >= self.max_total_entries {
    return false; // Reject new subnets
}

Для Orphan Pool Exhaustion:

// Добавить per-peer orphan limits
orphan_counts: HashMap<SocketAddr, usize>,
MAX_ORPHANS_PER_PEER: usize = 10,

// Проверять перед добавлением
if *self.orphan_counts.entry(peer).or_insert(0) >= MAX_ORPHANS_PER_PEER {
    return false;
}

Для Late Signature Buffer:

// Enforce max_size
impl LateSignatureBuffer {
    pub fn add(&mut self, proof: PresenceProof, ...) -> bool {
        let total_size: usize = self.pending.values().map(|v| v.len()).sum();
        if total_size >= self.max_size {
            return false; // Reject new late signatures
        }
        // ...
    }
}

Для AddrMan Poisoning:

// Добавить source reputation
pub fn add(&mut self, addr: NetAddress, source: Option<SocketAddr>) -> bool {
    if let Some(src) = source {
        if !self.is_source_reputable(src) {
            return false; // Reject addresses from disreputable sources
        }
    }
    // ...
}

7. Вердикт

[ ] CRITICAL — есть уязвимости, позволяющие уничтожить сеть [x] HIGH — есть серьёзные уязвимости [ ] MEDIUM — есть уязвимости среднего риска [ ] LOW — только minor issues [ ] SECURE — уязвимостей не найдено

Memory exhaustion в AdaptiveSubnetLimiter позволяет атакующему с IPv6 ботнетом вызвать OOM на full nodes, нарушая доступность сети. Orphan pool и late signature buffer уязвимы к DoS через memory exhaustion. AddrMan poisoning может привести к eclipse атакам. Эти уязвимости требуют срочного исправления для обеспечения сетевой безопасности Montana.