# DoS through PeerExplorer

Unbounded NodeChallengeManager.activeChallenges entries let an attacker flood unique NodeIDs to exhaust RSKj node memory and crash the JVM.

- Payout: $4,000
- Severity: high
- Program: Rootstock Labs
- Credited: z3t
- Disclosed: 2019-09-18
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/363636
- Library page: https://bugbountylibrary.com/r/h1%3A363636
- Tags: domain:network domain:oss impact:dos kind:bounty platform:hackerone sev:high tech:java technique:source-review vuln:dos

**Target:** RSKj peer discovery (PeerExplorer/NodeChallengeManager)
**Root cause:** startChallenge inserts into activeChallenges keyed by ping messageId, but entries are only removed when a matching pong arrives; the map is never purged or expired.
**Steps:**
1. Complete initial ping/pong handshake with target using a random NodeID.
2. Fill the target's NodeDistanceTable bucket (4096 default) so addConnection fails and startChallenge is invoked.
3. Never reply with pong matching the challenge ping's messageId, leaving the NodeChallenge in activeChallenges.
4. Repeat with many unique NodeIDs (multiple hosts to bypass per-address pending-ping limit of 65535/min).
5. Observe memory growth; ~200,000 insertions crashed the JVM with OutOfMemoryError.
**How found:** Code review of PeerExplorer.handlePong and NodeChallengeManager revealed the challenge entry is only removed on matching pong, and the map has no expiry/purge, prompting a flood PoC.
**Exploitation:** Attacker floods a peer-discovery-enabled node with handshakes using unique NodeIDs, filling the distance table and forcing unbounded NodeChallenge insertions that are never GC'd, exhausting heap until threads throw OutOfMemoryError and the JVM crashes.
**Insight:** When a challenge/state map is keyed by a message ID the peer controls, check whether removal depends on the peer cooperating; unremoved entries with no TTL are a memory-exhaustion primitive.
