10 KiB
Adversarial Review: Montana Network Layer
Модель: Claude Opus 4.5 Компания: Anthropic Дата: 07.01.2026 16:45 UTC
Executive Summary
Проведён анализ сетевого слоя Montana (/Montana ACP/montana/src/net/) на устойчивость к атакам. Проверены 5 критических векторов из шаблона Council.
Общий вердикт: NEEDS_FIX — обнаружено 2 уязвимости среднего уровня.
Роль
Атакующий с неограниченными ресурсами: ботнеты, множество IP-адресов из разных /16 подсетей, неограниченное время.
Цель: Eclipse жертвы, исчерпание ресурсов, нарушение консенсуса.
Attack Surface
- External inputs: TCP соединения, P2P сообщения, адреса от peers
- Trust boundaries: inbound peers (недоверенные), outbound peers (частично доверенные)
- Critical assets: consensus view, address manager state, connection slots
TIER 0: КРИТИЧЕСКИЕ ВЕКТОРЫ
1. Eclipse Attack
Файлы: addrman.rs, eviction.rs, connection.rs
Проверенные защиты
| Механизм | Статус | Код |
|---|---|---|
| Netgroup diversity (/16) | PROTECTED | connection.rs:253-257 |
| Cryptographic bucketing | PROTECTED | addrman.rs:445-475 |
| Self-connection detection | PROTECTED | protocol.rs:768-772 |
| Eviction multi-layer | PROTECTED | eviction.rs:65-126 |
| Anchor connections | NOT IMPLEMENTED | — |
Attempted Attacks
| # | Attack | Result |
|---|---|---|
| 1 | Заполнить NEW table вредоносными адресами | MITIGATED — cryptographic bucketing распределяет по source |
| 2 | Продвинуть в TRIED через fake connections | MITIGATED — требует реальное TCP соединение |
| 3 | Occupy all outbound slots from same /16 | PROTECTED — MAX_PEERS_PER_NETGROUP = 2 |
| 4 | Gaming eviction (fake low latency) | PROTECTED — 6-layer protection (28 slots) |
| 5 | Post-restart eclipse | VULNERABLE — нет anchor connections |
Finding: Anchor Connections Missing
Severity: MEDIUM
Описание: После рестарта узла все outbound соединения выбираются заново из AddrMan. Если атакующий заранее заполнил NEW/TRIED таблицы вредоносными адресами (даже распределёнными по разным /16), после рестарта жертва может подключиться к 8 узлам атакующего.
Эксплуатация:
1. Атакующий получает IPs в 8+ разных /16 подсетях
2. Заполняет AddrMan жертвы через Addr сообщения (1000 addr/msg)
3. Ждёт рестарт жертвы (обновление, сбой)
4. Жертва выбирает 8 outbound из отравленного AddrMan
5. Все 8 outbound → атакующий, eclipse достигнут
Mitigating factors:
- Требует 8+ IPs в разных /16 (дорого, но достижимо)
- Rate limiting на Addr (0.1/sec sustained) замедляет отравление
- Жертва должна перезапуститься
Рекомендация:
Реализовать anchor connections — сохранять 2 последних успешных outbound peers и подключаться к ним первыми после рестарта. Bitcoin Core: net.cpp:2098-2150.
2. Memory Exhaustion
Файлы: protocol.rs, sync.rs, rate_limit.rs
Проверенные защиты
| Механизм | Статус | Код |
|---|---|---|
| Flow control BEFORE read | PROTECTED | protocol.rs:647-658 |
| Early size check (4MB) | PROTECTED | protocol.rs:1114-1119 |
| Bounded deserialize | PROTECTED | protocol.rs:1138-1141 |
| OrphanPool bounded | PROTECTED | sync.rs:38 (100 orphans) |
| BoundedInvSet | PROTECTED | peer.rs:35-87 (100k items) |
| AddrMan file limit | PROTECTED | addrman.rs:29 (16MB) |
Attempted Attacks
| # | Attack | Result |
|---|---|---|
| 1 | Send msg with length=2^32 | PROTECTED — early check vs MAX_SLICE_SIZE (4MB) |
| 2 | Flow control bypass | PROTECTED — check BEFORE read_message() |
| 3 | Orphan slice flooding | PROTECTED — MAX_ORPHANS=100, FIFO eviction |
| 4 | Known inventory exhaustion | PROTECTED — BoundedInvSet, FIFO eviction |
| 5 | Malicious bincode length prefix | PROTECTED — bounded deserialize with_limit() |
Verdict: SAFE
Память защищена на всех уровнях. Flow control исправлен после Gemini audit (комментарий в protocol.rs:635).
TIER 1: ВЫСОКИЕ ВЕКТОРЫ
3. Connection Slot Exhaustion
Файлы: connection.rs, eviction.rs
Attempted Attacks
| # | Attack | Result |
|---|---|---|
| 1 | Occupy all 117 inbound slots | PARTIAL — eviction может освободить |
| 2 | Gaming eviction via fake metrics | PROTECTED — 6-layer, 28 protected slots |
| 3 | Rapid connect/disconnect flooding | POTENTIAL — нет per-IP rate limit |
Finding: Connection Rate Limiting Per-IP
Severity: LOW
Описание: Нет явного rate limiting на новые TCP соединения от одного IP. Атакующий может быстро открывать и закрывать соединения, создавая нагрузку на listener loop.
Mitigating factors:
- Exponential backoff в
connection.rs:139-173работает только для outbound - TCP handshake сам по себе ограничивает скорость
- OS-level connection limits
Рекомендация: Добавить per-IP connection rate limit в listener_loop: max 5 connections per IP per minute.
4. Sync DoS
Файлы: sync.rs, bootstrap.rs, protocol.rs
Attempted Attacks
| # | Attack | Result |
|---|---|---|
| 1 | GetSlices amplification | PROTECTED — count.min(500) в protocol.rs:1036 |
| 2 | GetData abuse | PROTECTED — rate_limits.getdata (1000 burst, 5/sec) |
| 3 | Headers flooding | POTENTIAL — нет rate limit на SliceHeaders |
Finding: Headers Rate Limiting
Severity: MEDIUM
Описание: Нет явного rate limit на получение SliceHeaders сообщений. Атакующий может слать большие headers responses, вызывая CPU exhaustion на валидации.
Проверка в коде:
Message::SliceHeadersне имеет rate limiter вPeerRateLimits- MAX_HEADERS_SIZE = 512KB (2000 headers × 256 bytes)
- Обработка headers требует валидации каждого
Эксплуатация:
1. Подключиться к жертве
2. Слать GetHeaders запросы
3. Отвечать 2000 headers каждый раз
4. Жертва тратит CPU на валидацию
5. Повторить с множества соединений
Рекомендация: Добавить HeadersRateLimiter в PeerRateLimits: 5000 headers burst, 10/sec sustained.
5. Rate Limit Bypass
Файл: rate_limit.rs
Attempted Attacks
| # | Attack | Result |
|---|---|---|
| 1 | Multiple connections bypass | CONFIRMED — rate limits per-connection |
| 2 | Token bucket timing | SAFE — refill() calls Instant::now() |
| 3 | Message type gaps | PARTIAL — Headers/Presence not rate limited |
Finding: Per-Connection vs Per-IP
Severity: LOW
Описание:
Rate limits в PeerRateLimits применяются per-connection. Атакующий с 10 соединениями получает 10× burst capacity.
Пример:
- Addr: 1000 burst per connection
- 10 connections = 10,000 addr burst
- Это ускоряет AddrMan poisoning
Mitigating factors:
- MAX_INBOUND = 117 ограничивает масштаб
- Netgroup diversity (/16) ограничивает connections per attacker
Рекомендация: Рассмотреть глобальный per-IP rate tracker для критических message types.
Checklist Results
[x] Eclipse: netgroup diversity работает
[ ] Eclipse: anchor connections есть ← MISSING
[x] Memory: flow control до allocation
[x] Memory: orphan pool bounded
[x] Memory: все collections bounded
[x] Slots: eviction защищает diversity
[ ] Sync: headers rate limited ← MISSING
[x] Sync: GetSlices rate limited
[ ] Rate: все messages covered ← PARTIAL
[x] Rate: per-IP limiting (partial via netgroup)
Summary of Findings
| # | Finding | Severity | Status |
|---|---|---|---|
| 1 | Missing anchor connections | MEDIUM | NEEDS_FIX |
| 2 | Headers not rate limited | MEDIUM | NEEDS_FIX |
| 3 | Connection rate per IP | LOW | CONSIDER |
| 4 | Per-connection vs per-IP rate | LOW | CONSIDER |
Positive Observations
- Flow control: Исправлен после Gemini audit, теперь блокирует read ПЕРЕД allocation
- Bounded collections: Все структуры данных имеют лимиты с FIFO eviction
- Eviction system: 6-layer protection делает gaming очень сложным
- Cryptographic bucketing: SipHash24 с секретным ключом предотвращает bucket prediction
- Self-connection detection: Nonce-based detection работает корректно
- Bounded deserialize: bincode with_limit() везде где нужно
Verdict
[ ] SAFE — можно продолжать
[x] NEEDS_FIX — исправить перед продолжением
Critical: 0
High: 0
Medium: 2 (anchor connections, headers rate limit)
Low: 2 (connection rate, per-IP rate)
References
- Bitcoin Core anchor connections:
net.cpp:2098-2150 - Bitcoin Core headers rate limit:
net_processing.cpp:HEADERS_DOWNLOAD_TIMEOUT_BASE - Erebus attack paper: https://erebus-attack.comp.nus.edu.sg/
Report generated by Claude Opus 4.5 (Anthropic) Security Council Review — Montana ACP