← Back to Research
Research · July 28, 2026

Qtum BIP-324 Pre-Authentication ECDH CPU Exhaustion

Simon Morley·3 min read

Qtum's BIP-324 v2 transport runs a pre-authentication ellswift-ECDH on every inbound connection, allowing a single source IP to saturate a core and deny honest peers.

Why this matters

The inbound peer-protocol listener (mainnet port 3888) is reachable by default on qtumd nodes. Because the asymmetric-crypto handshake occurs before any authentication or rate-limiting, a single source IP can pin one CPU core, and a small distributed fleet can measurably degrade or deny honest peers' ability to connect. This results in an availability DoS characterised by fullnode peering degradation, though it does not halt consensus (PoS block production is a separate path).

How the attack works

The attack targets the BIP-324 v2 transport responder, which is enabled by default (DEFAULT_V2_TRANSPORT{true} at src/net.h:95). When an inbound connection sends its 64-byte ellswift key, the node immediately executes Initialize (src/net.cpp:1140-1147), triggering a secp256k1 ellswift ECDH plus HKDF-SHA256 key derivation (src/bip324.cpp:41-64). This expensive cryptographic operation runs BEFORE any authentication, allowlist, per-IP rate limit, or proof-of-work gate. The only inbound cap (maxconnections=125) is soft: when full, the node calls AttemptToEvictConnection (src/net.cpp:1815) to evict an existing peer and admit the new socket. As the v2 accept path is single-threaded, a churn of fresh inbound sockets from even one source IP can saturate the path and consume CPU resources.

Affected systems

This behaviour was verified on qtumd v29.1.0 (commit 7641affd / tag v29.1, SHA256 c04e3f49…). The affected component is the P2P inbound transport (BIP-324 v2 responder). The default mainnet P2P port is 3888 (testnet 13888, regtest 23888).

Evidence

Publicly documented No CVE is assigned for this finding.

Independently reproduced by NullRabbit The reproducer probe_qtum_bip324.py simulates the attack by generating a churn of inbound TCP connections. In "churn" mode, it opens a TCP connection, sends a 64-byte ellswift key to trigger the ECDH, and immediately closes the connection. In "hold" mode, it sends the key and holds the connection to occupy an inbound slot.

Measured under controlled conditions Loopback (isolated regtest, qtumd v29.1.0): The attack held 96.3% average / 100% median of one core over a 60-second run, achieving 14,275 handshakes/s (vs 0.3% baseline). It demonstrated approximately 39.6× egress amplification and filled all 114 inbound slots via eviction-on-full behaviour.

DigitalOcean (production-shape, 4-IP distributed attack): Honest-peer v2 handshake latency increased from a p50 baseline of 32 ms to 3371 ms (107×) under a 4-IP attack, with p99 latency reaching 9656 ms (182×). The test observed 11% outright connection denial at the 4-IP shape. A single attacker IP caused a 65× increase in p50 latency.

Inferred but not reproduced None.

Operator actions

NullRabbit recommends the following mitigations:

  1. Cost-gate the pre-auth crypto: Apply a per-source-IP budget, cheap proof-of-work, or connection-rate cap BEFORE the ellswift-ECDH runs to prevent unauthenticated peers from forcing unbounded asymmetric-crypto work.
  2. Make the v2 accept path concurrent: Modify the implementation so a single IP cannot serialise or saturate the accept path.
  3. Harden the inbound cap: Reserve slots for established or outbound-verified peers so that fresh-socket churn cannot evict honest peers (modifying AttemptToEvictConnection).

Canonical references

Related attacks

This finding is the same class and magnitude as the measured Bitcoin Core BIP-324 finding (BTC_V0_BIP324_PREHANDSHAKE_CPU).

Subscription call to action

Track attacks affecting qtum.

Analysis plus reproducer. No weaponised proof-of-concept code.

qtumqtumdp2pbip324compute_ampinfrastructure-security
Publication policy:Why we publish these findings →

Related Posts

What syscall-layer tooling cannot see in P2P infrastructure: a technique-by-technique analysis

·14 min read

If you run Falco, an EDR, or a generic host agent on a validator and a network-DoS attack against the node went undetected, this explains why. A technique-by-technique analysis of five reproduced P2P-infrastructure attacks against the syscall detection surface. Zero are detectable as attributable rules, and the reasons are structural, not a matter of tuning.

researchdetectionfalco+6 more

How a zero-value GetBlockHeaders request underflows to serve go-ethereum's entire header chain (CVE-2024-32972)

·7 min read

A go-ethereum eth-protocol peer that sends a GetBlockHeaders request with amount (count) set to 0 triggers an integer underflow — count-1 wraps to UINT64_MAX — bypassing the maxHeadersServe cap and forcing the node to serve headers back to genesis, a publicly disclosed memory-exhaustion DoS (CVE-2024-32972, fixed in geth 1.13.15) that NullRabbit reproduced as a lab detection bundle.

ethereumgo-ethereumdevp2p+4 more