11 KiB
Security Audit: Lottery Grinding & Bootstrap DoS
Модель: Gemini 3 Pro Компания: Google Дата: 08.01.2026 16:30 UTC
1. Понимание архитектуры
Montana ACP (Atemporal Coordinate Presence) — это сеть, где консенсус достигается не через PoW/PoS, а через "накопление присутствия" (время). Узлы подписывают временные слоты (таймслайсы), доказывая своё существование. Победитель раунда (каждые 10 минут, τ₂) выбирается через детерминированную лотерею.
Ключевые механизмы защиты:
- Детерминированная лотерея: Должна зависеть только от предыдущего состояния сети (хеш прошлого слайса), чтобы исключить манипуляции (grinding) в текущем раунде.
- Adaptive Cooldown: Защита от Sybil через временнУю стоимость входа (1-180 дней).
- Adaptive Subnet Limiter: Защита от сетевых атак (Erebus/DoS) через двухуровневые лимиты подсетей.
Я изучил архитектуру и обнаружил критическую уязвимость в реализации консенсуса.
2. Изученные файлы
| Файл | LOC | Ключевые компоненты |
|---|---|---|
montana/src/consensus.rs |
271 | Логика лотереи, расчет seed, проверка победителя |
montana/src/net/rate_limit.rs |
1183 | Реализация лимитеров, AdaptiveSubnetLimiter |
montana/src/net/protocol.rs |
1653 | Основной сетевой протокол, обработка сообщений |
montana/src/net/bootstrap.rs |
1254 | Логика начальной загрузки и верификации |
montana/src/cooldown.rs |
262 | Реализация адаптивного кулдауна |
3. Attack Surface
Я определил следующие векторы атак:
- Манипуляция лотереей (Grinding): Возможность влиять на выбор победителя через изменение содержимого блока.
- Блокировка запуска (Bootstrap DoS): Манипуляция медианой сети для принудительного отказа в обслуживании новым узлам.
4. Найденные уязвимости
[CRITICAL] Lottery Grinding (Манипуляция лотереей)
Файл: montana/src/consensus.rs:23
Уязвимый код:
pub fn compute_lottery_seed(prev_hash: &Hash, tau2_index: u64, presence_root: &Hash) -> Hash {
let mut data = Vec::with_capacity(72);
data.extend_from_slice(prev_hash);
data.extend_from_slice(&tau2_index.to_le_bytes());
data.extend_from_slice(presence_root); // <--- КРИТИЧЕСКАЯ ОШИБКА
sha3(&data)
}
Описание:
В документации (layer_1.md) явно указано, что seed = SHA3-256(prev_slice_hash ‖ τ₂_index). Это гарантирует, что победитель определен до формирования блока.
Однако в коде в расчет seed включен presence_root текущего блока.
Поскольку presence_root зависит от набора подписей, включенных в блок, а блок формирует сам победитель, это создает циклическую зависимость, которую атакующий может эксплуатировать.
Вектор атаки:
- Атакующий (даже с минимальным весом) собирает подписи присутствия (presence signatures) от других узлов.
- Вместо публикации всех подписей, атакующий перебирает различные подмножества подписей.
- Для каждого подмножества вычисляется новый
presence_root. - Новый
presence_rootдает новыйseedлотереи. - Новый
seedменяет победителя (функцияfind_winner). - Атакующий повторяет перебор (Grinding), пока не найдет такой
presence_root, при которомseedделает его победителем. - Атакующий публикует валидный блок, где он — законный победитель.
Импакт: Атакующий с минимальным весом может выигрывать лотерею практически в каждом раунде, просто перебирая комбинации подписей. Это полностью ломает модель консенсуса, основанную на времени/весе, и превращает её в PoW-гонку (где "работа" — это хеширование комбинаций подписей). Захват сети возможен с одним слабым узлом.
Сложность: Низкая. Требуется только CPU для хеширования.
PoC сценарий:
// Псевдокод атаки
let signatures = collect_mempool_signatures();
let my_pubkey = my_keypair.public;
for subset in signatures.powerset() {
let root = compute_merkle_root(subset);
let seed = compute_lottery_seed(prev_hash, index, root);
let (winner, _) = find_winner(seed, all_participants);
if winner == my_pubkey {
publish_block(subset); // PROFIT!
break;
}
}
[MEDIUM] Bootstrap DoS via Consensus Manipulation
Файл: montana/src/net/bootstrap.rs:326 (verify_hardcoded_consensus)
Описание: При запуске узел опрашивает 100 пиров (из которых ~20 hardcoded). Он вычисляет медиану высоты цепи по всем ответам. Затем он требует, чтобы каждый hardcoded узел соответствовал этой медиане (с допуском 1%). Если hardcoded узлы отклоняются (потому что медиана смещена атакой), загрузка прерывается с ошибкой CRITICAL.
Вектор атаки: Атакующий окружает новый узел своими пирами (Eclipse) и сообщает ложную высоту (например, сильно большую или малую). Медиана по всем 100 пирам смещается в сторону атакующего. Честные hardcoded узлы (которые сообщают реальную высоту) оказываются "несогласными" с медианой. Узел считает, что hardcoded узлы скомпрометированы, и аварийно останавливается.
Импакт: Полный отказ в обслуживании (DoS) для новых узлов. Они не могут присоединиться к сети.
Сложность: Средняя (требуется контроль входящих соединений жертвы).
5. Атаки, которые НЕ работают
- Erebus / Subnet Flood: Код
GlobalSubnetLimiterвrate_limit.rsкорректно реализует двухуровневую защиту (Fast/Slow tiers) и правильно интегрирован вprotocol.rs(вызовыsubnet_limiter.check()). Это защищает от атак с использованием множества IP из одной подсети. - Sybil (регистрация):
AdaptiveCooldownреализован корректно вcooldown.rs. Спам регистрациями действительно приведет к увеличению кулдауна до 180 дней. - Fake Hardcoded Nodes:
HardcodedNodeаутентификация через ML-DSA-65 реализована и работает. Подделать hardcoded узел без приватного ключа нельзя. - Inventory Exhaustion:
BoundedInvSetиспользует FIFO удаление старых элементов, что защищает память даже при флуде уникальными инвентарными хешами.
6. Рекомендации
-
Исправить Lottery Grinding (СРОЧНО): Исключить
presence_rootиз расчетаseedвconsensus.rs. Seed должен зависеть только отprev_hashиindex.// Было: // data.extend_from_slice(presence_root); // Стало: // (удалить эту строку)Это сделает лотерею честной: победитель определяется до того, как он сможет манипулировать содержимым блока.
-
Улучшить логику Bootstrap: Вместо аварийной остановки при несогласии hardcoded узлов с медианой сети, следует использовать "Trusted Core" подход:
- Собрать ответы от всех hardcoded узлов.
- Вычислить медиану ТОЛЬКО среди hardcoded узлов (
hardcoded_median). - Проверить консенсус внутри hardcoded группы (сколько узлов в пределах ±1% от
hardcoded_median). - Если большинство (>50%) hardcoded узлов согласны → считать
hardcoded_medianистинной. - P2P узлы проверять относительно этой доверенной медианы (warning при расхождении, но не блокировка).
- Hardcoded узлы, которые не согласны с
hardcoded_median(меньшинство), игнорируются, но не вызывают падения. Это сделает bootstrap устойчивым к Eclipse-атакам, так как атакующий не может подделать подписи hardcoded узлов.
7. Вердикт
[x] CRITICAL — есть уязвимости, позволяющие уничтожить сеть (Lottery Grinding позволяет захватить контроль над блокчейном). [ ] HIGH [ ] MEDIUM [ ] LOW [ ] SECURE