-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Description
Summary
The BlockManager in consensus-core has two vulnerabilities related to missing_blocks:
-
Unbounded Growth: The
missing_blocksset can grow without bound when Byzantine validators produce blocks referencing non-existent ancestors, leading to OOM. -
Future-Flooding Attack: A naive "lowest rounds first" eviction strategy can be exploited by attackers to evict legitimate missing blocks by flooding with high-round garbage.
Problem
The code contains an explicit TODO acknowledging the first issue:
/// TODO: As it is possible to have Byzantine validators who produce Blocks without valid causal
/// history we need to make sure that BlockManager takes care of that and avoid OOM (Out Of Memory)
/// situations.
When a block references ancestors that do not exist (and cannot be fetched), these are added to missing_blocks without any upper bound. A Byzantine validator can continuously produce blocks with fake ancestor references, causing unbounded memory growth.
Additionally, a naive "lowest rounds first" eviction strategy would allow attackers to:
- Wait until the node has legitimate missing blocks (e.g., P at Round 10)
- Flood with garbage blocks referencing fake parents at high rounds (e.g., Round 1000)
- When capacity is reached, the eviction strategy removes lowest rounds first
- Result: Legitimate block P (Round 10) is evicted while garbage is retained
Impact
- Liveness Risk: Medium - Memory exhaustion OR legitimate blocks evicted
- Safety Risk: Low - Does not affect block processing correctness
- Agreement Risk: Low - Does not affect consensus decisions
Attack Vectors
Vector 1: OOM Attack
- Attacker must be a committee member (hold signing keys)
- Each block can reference up to
committee_sizefake ancestors - Each fake ancestor adds ~100 bytes to memory
- At realistic attack speed (200ms/round): ~149 hours to exhaust 1GB
Vector 2: Future-Flooding Attack
- Node at Round 10 has legitimate missing parent P (Round 10)
- Attacker floods with blocks referencing Round 1000 fake parents
- Naive eviction removes P first (lowest round) - Liveness failure
Proposed Fix
- Add
MAX_MISSING_BLOCKSconstant (100,000 entries, ~10MB max) - Add
gc_missing_blocks()method with distance-based eviction:- Define protection window around current round (±50 rounds)
- Prioritize evicting entries FAR from current round (likely garbage)
- Protect entries NEAR current round (likely legitimate)
- Add capacity checks before inserting new missing blocks
Affected Code
consensus/core/src/block_manager.rs-BlockManager::try_accept_one_block()andBlockManager::try_find_blocks()