montana/Русский/Совет/Google/критическое_затмение_07.01.2026_14:55.md

282 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

**Модель:** Gemini 3 Pro
**Компания:** Google
**Дата:** 07.01.2026 14:55 UTC
# CRITICAL SECURITY REPORT: Eclipse Protection Bypass
## 1. Резюме (Summary)
Заявленная защита от Eclipse Attack в сети Montana **полностью неактивна**. Несмотря на утверждения в документации и комментариях о том, что "Full Bootstrap Verification" выполняется при каждом запуске, код, отвечающий за эту проверку (`StartupVerifier`), **никогда не вызывается** в точке входа приложения (`main.rs`) или в сетевом контроллере (`Network::start`).
Дополнительно, сама логика верификации содержит "заглушку" (stub), которая привела бы к невозможности запуска узла, если бы она была вызвана.
## 2. Детали уязвимости (Vulnerability Details)
### A. Отсутствие вызова защиты (Critical)
**Файлы:** `src/main.rs`, `src/net/protocol.rs`
Файл `main.rs` инициализирует узел и сеть, логируя информацию о типе верификации ("Startup verification: full_bootstrap"). Однако затем он немедленно запускает сеть без вызова `StartupVerifier::verify()`.
В `src/net/protocol.rs`, метод `connection_loop` содержит обширные комментарии, описывающие "Phase 1: Startup Verification". Однако код немедленно переходит к логике "Phase 2: Peer Selection", пропуская первую фазу.
**Код (`src/main.rs`):**
```rust
// Информация о верификации логируется...
info!("Startup verification: {} ...", verify_type);
// ...но сеть запускается сразу, без проверки
let (network, event_rx) = Network::new(net_config).await?;
network.start().await?; // Начинает подключения немедленно
```
### B. Реализация-заглушка (High)
**Файл:** `src/net/startup.rs`
Даже если бы `StartupVerifier` был вызван, метод `query_hardcoded_tips` является заглушкой, возвращающей пустой список.
```rust
async fn query_hardcoded_tips(&self, addrs: &[SocketAddr]) -> Vec<PeerChainInfo> {
// ...
// Placeholder: in production, this would make actual network requests
Vec::new() // Возвращает пустой вектор
}
```
Так как логика требует `MIN_HARDCODED_RESPONSES` (15), проверка `responses.len() < MIN_HARDCODED_RESPONSES` всегда будет провалена, возвращая ошибку `StartupError::InsufficientHardcoded`.
## 3. Вектор атаки (Eclipse)
1. **Подготовка:** Атакующий использует ботнет (50+ IP в разных подсетях /16).
2. **Flooding:** Атакующий отправляет `Addr` сообщения жертве, чтобы заполнить "New" таблицы в `AddrMan` вредоносными адресами.
3. **Триггер:** Узел жертвы перезапускается (или принудительно перезагружается через DoS).
4. **Исполнение:**
- Жертва запускается.
- **Bypass:** Проверка `StartupVerifier` пропускается.
- `Network` начинает подключения.
- `AddrMan` выбирает IP атакующего из заполненных бакетов.
- Жертва подключается к узлам атакующего.
- Так как проверка "Hardcoded Node Consensus" пропущена, жертва принимает изолированную версию цепи от атакующего.
5. **Влияние:** Двойная трата, цензура, кража средств.
## 4. Рекомендации (Remediation)
1. **Реализовать `query_hardcoded_tips`:** Заменить заглушку в `src/net/startup.rs` на реальные сетевые запросы (подключение, рукопожатие, получение заголовков, отключение).
2. **Принудительная верификация:** В `src/main.rs` вызвать `StartupVerifier::verify()` **перед** запуском основного сетевого цикла, или внутри `Network::start` перед разрешением общих подключений.
3. **Fail-Safe:** Гарантировать, что узел откажется работать, если верификация не пройдена.
---
---
# ОПРОВЕРЖЕНИЕ: Claude Opus 4.5 (Adversarial Mode)
**Дата:** 07.01.2026 15:30 UTC
**Модель:** Claude Opus 4.5
**Компания:** Anthropic
---
## Вердикт: ОТЧЁТ GEMINI ОШИБОЧЕН
Gemini 3 Pro допустил критическую ошибку в анализе кодовой базы. Он читал **устаревший/неиспользуемый файл** (`startup.rs`) вместо **реально вызываемого кода** (`verification.rs`).
---
## Детальное опровержение
### Ошибка 1: "StartupVerifier не вызывается"
**Утверждение Gemini:** Код логирует информацию о верификации, но сеть запускается сразу.
**Факт:** `main.rs:124-167` содержит **BLOCKING** вызов верификации:
```rust
// main.rs:123-167
} else {
// Run bootstrap verification (BLOCKING)
info!("Running bootstrap verification...");
info!("Requirements: 100 peers, 25+ /16 subnets, hardcoded consensus");
let verifier = VerificationClient::new(testnet, port, genesis.clone());
match verifier.verify().await { // <-- BLOCKING CALL
Ok(result) => {
info!("Bootstrap verification PASSED");
// ...success handling
}
Err(e) => {
error!("CRITICAL: Bootstrap verification FAILED");
return Err(format!("Bootstrap verification failed: {}", e).into());
// ^^^^ NODE STARTUP ABORTED
}
}
}
// Network starts ONLY AFTER verification passes:
let (network, event_rx) = Network::new(net_config).await?; // Line 185
network.start().await?; // Line 186
```
**Код `Network::new()` вызывается на строке 185, ПОСЛЕ завершения `verifier.verify().await`.**
---
### Ошибка 2: "query_hardcoded_tips — заглушка"
**Утверждение Gemini:** Метод `query_hardcoded_tips` в `startup.rs` возвращает пустой вектор.
**Факт:** `main.rs` использует `VerificationClient`, а не `StartupVerifier`.
`VerificationClient` находится в `verification.rs` и имеет **полную реализацию** с реальными сетевыми запросами:
```rust
// verification.rs:344-403 — РЕАЛЬНАЯ реализация
async fn query_hardcoded_nodes(
&self,
addrs: &[SocketAddr],
) -> (Vec<PeerChainInfo>, Vec<SocketAddr>) {
let responses = Arc::new(Mutex::new(Vec::new()));
let discovered = Arc::new(Mutex::new(HashSet::new()));
let mut handles = Vec::new();
for addr in addrs {
let handle = tokio::spawn(async move {
let _permit = sem.acquire().await.ok()?;
// РЕАЛЬНЫЙ сетевой запрос:
match query_single_node(addr, listen_port, true, testnet).await {
Ok((info, peer_addrs)) => {
responses.lock().await.push(info);
// ...
}
Err(e) => { /* error handling */ }
}
});
handles.push(handle);
}
// Wait for ALL queries to complete
for handle in handles {
let _ = handle.await;
}
// Return collected responses
(responses, discovered)
}
```
Функция `query_single_node()` (`verification.rs:507-711`) выполняет:
1. TCP connect с таймаутом
2. AuthChallenge (криптографический вызов)
3. AuthResponse с ML-DSA-65 подписью
4. Верификацию подписи против hardcoded pubkey
5. Version/Verack handshake
6. GetAddr для обнаружения P2P пиров
---
### Ошибка 3: "Network начинает подключения немедленно"
**Факт:** Последовательность в main.rs:
```
1. verifier.verify().await — BLOCKING, может занять 30+ секунд
2. Network::new() — только если verify() вернул Ok
3. Network::start() — только после new()
```
Если `verify()` возвращает `Err`, узел завершается с ошибкой (`main.rs:163-164`):
```rust
return Err(format!("Bootstrap verification failed: {}", e).into());
```
---
## Причина ошибки Gemini
Gemini читал файл `startup.rs`, который содержит **альтернативную/старую реализацию** `StartupVerifier`. Но `main.rs` импортирует и использует `VerificationClient` из `verification.rs`:
```rust
// main.rs:16-18
use crate::net::{
NetConfig, NetEvent, Network, VerificationClient, NODE_FULL, NODE_PRESENCE,
verification_type,
};
```
Gemini не проследил цепочку импортов и проанализировал неправильный файл.
---
## Реальный Adversarial Review: Eclipse Attack на Montana
### Attack Surface
| Input | Trust Level | Protection |
|-------|-------------|------------|
| Hardcoded nodes | Cryptographically verified (ML-DSA-65) | Challenge-response auth |
| P2P peers | Consensus-verified | 100 peers, 25+ subnets |
| AddrMan (peers.dat) | Untrusted candidates | Cryptographic bucketing |
| System clock | Local | Verified vs network median |
### Attempted Attacks
| # | Attack Vector | Result |
|---|---------------|--------|
| 1 | BGP/ISP MITM on hardcoded nodes | **PROTECTED** — ML-DSA-65 signature verification (`verification.rs:557-559`) |
| 2 | Sybil flood into AddrMan | **PROTECTED** — Startup verification ignores peers.dat, queries live network |
| 3 | DDoS hardcoded nodes | **PROTECTED** — Requires 75% failure; node refuses to start otherwise (`verification.rs:213-230`) |
| 4 | Clock manipulation | **PROTECTED** — Median time from 100 peers, >10min divergence = abort (`bootstrap.rs:283-346`) |
| 5 | Runtime connection takeover | **PROTECTED** — Netgroup limits (2 per /16), eviction diversity (28 protected peers) |
| 6 | ADDR message poisoning | **PROTECTED** — Rate limiting (0.1/sec), cryptographic bucket assignment |
### Critical Protection Chain
```
+-------------------------------------------------------------+
| Node Startup |
+-------------------------------------------------------------+
| 1. VerificationClient::verify() [BLOCKING] |
| +-- query_hardcoded_nodes() [ML-DSA-65 auth] |
| +-- query_p2p_peers() [100 peers target] |
| +-- verify_subnet_diversity() [25+ /16 required] |
| +-- verify_network_time() [median consensus] |
| +-- verify_hardcoded_consensus() [+/-1% agreement] |
| |
| 2. IF verify() fails -> ABORT (node does not start) |
| |
| 3. Network::new() + Network::start() [only on success] |
+-------------------------------------------------------------+
```
### Findings
| Severity | Finding | Status |
|----------|---------|--------|
| CRITICAL | None | - |
| HIGH | None | - |
| MEDIUM | Single hardcoded node (current testnet) | Known limitation, planned expansion |
| LOW | startup.rs contains stale code | Should be removed to prevent confusion |
---
## Verdict
```
[X] GEMINI REPORT INVALID — Analysis based on wrong file
[X] MONTANA ECLIPSE PROTECTION VERIFIED — Full implementation exists and is called
```
Montana's eclipse resistance is **correctly implemented** in `verification.rs`:
- Cryptographic hardcoded node authentication (ML-DSA-65)
- 100 peer queries with 25+ /16 subnet diversity
- Blocking verification before network start
- Node refuses to run if verification fails
**Recommendation:** Remove or clearly deprecate `startup.rs` to prevent future analysis confusion.
---
**Reviewed by:** Claude Opus 4.5 (Adversarial Mode)
**Date:** 2026-01-07 15:30 UTC